diff --git a/ChangeLog b/ChangeLog index 8188a60a22..1d9ec33b01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2004-11-22 Dan Williams + + * src/NetworkManagerDevicePrivate.h + - Split out the NMDevice struct to a different file so that stuff like + NetworkManagerDHCP.c and NetworkManagerSystem.c can use it + + * dhcpcd/client.c + - fprintf->syslog + - (dhcpSendAndRecv): do non-blocking sends and receives, and check to see if we + need to cancel the dhcp request during the send and recv + + * dhcpcd/client.h + - Move the DHCP option enum to dhcpcd.h + + * src/NetworkManagerDHCP.c + - Split out the actual IP/netmask/etc setting code + - New Renew/Rebind functions + - New timer setup function for renew/rebind operations + + * src/NetworkManagerDevice.c + - For device activation, if we are using DHCP then keep the activation thread + alive until device deactivation. We need to renew/rebind the DHCP address + after the T1 (renew) and T2 (rebind) times have expired. + - Increase some timeouts after bringing wireless cards up/down + 2004-11-17 Dan Williams * Cache access point MAC addresses in NetworkManagerInfo after you've explicitly diff --git a/dhcpcd/client.c b/dhcpcd/client.c index 146518fe14..5f79da98dd 100644 --- a/dhcpcd/client.c +++ b/dhcpcd/client.c @@ -295,7 +295,7 @@ void classIDsetup(dhcp_interface *iface, const char *g_cls_id) { struct utsname sname; if ( uname(&sname) ) - syslog(LOG_ERR,"classIDsetup: uname: %m\n"); + syslog (LOG_ERR,"classIDsetup: uname: %m\n"); snprintf (iface->cls_id, DHCP_CLASS_ID_MAX_LEN, "%s %s %s", sname.sysname, sname.release, sname.machine); } @@ -506,7 +506,7 @@ int dhcpSendAndRecv (dhcp_interface *iface, unsigned int expected_reply_type, { udpipMessage *udp_msg_recv = NULL; struct sockaddr addr; - int len, err, local_timeout = 0; + int len, err = RET_DHCP_TIMEOUT, local_timeout = 0; int j = DHCP_INITIAL_RTO / 2; struct timeval local_begin, current, diff; struct timeval overall_end; @@ -519,6 +519,7 @@ int dhcpSendAndRecv (dhcp_interface *iface, unsigned int expected_reply_type, do { udpipMessage *udp_msg_send = buildUdpIpMsg (iface); + int send_err = 0; if (!udp_msg_send) return RET_DHCP_ERROR; @@ -546,12 +547,16 @@ int dhcpSendAndRecv (dhcp_interface *iface, unsigned int expected_reply_type, memset (&addr, 0, sizeof(struct sockaddr)); memcpy (addr.sa_data, iface->iface, strlen (iface->iface)); - if (sendto (iface->sk, udp_msg_send, len, 0, &addr, sizeof(struct sockaddr)) == -1) + do { - syslog (LOG_ERR,"sendto: %m\n"); - free (udp_msg_send); - return RET_DHCP_ERROR; - } + send_err = sendto (iface->sk, udp_msg_send, len, MSG_DONTWAIT, &addr, sizeof(struct sockaddr)); + if (iface->cease || ((send_err == -1) && (errno != EAGAIN))) + { + free (udp_msg_send); + return iface->cease ? RET_DHCP_CEASED : RET_DHCP_ERROR; + } + } while ((send_err == -1) && (errno == EAGAIN)); + free (udp_msg_send); gettimeofday (&local_begin, NULL); err = peekfd (iface, (j + random () % 200000)); @@ -571,13 +576,15 @@ int dhcpSendAndRecv (dhcp_interface *iface, unsigned int expected_reply_type, udp_msg_recv = calloc (1, sizeof (udpipMessage)); o = sizeof (struct sockaddr); - len = recvfrom (iface->sk, udp_msg_recv, sizeof(udpipMessage), 0, (struct sockaddr *)&addr, &o); - if (len == -1) + do { - syslog(LOG_ERR,"recvfrom: %m\n"); - free (udp_msg_recv); - return RET_DHCP_ERROR; - } + len = recvfrom (iface->sk, udp_msg_recv, sizeof(udpipMessage), MSG_DONTWAIT, (struct sockaddr *)&addr, &o); + if (iface->cease || ((len == -1) && (errno != EAGAIN))) + { + free (udp_msg_recv); + return iface->cease ? RET_DHCP_CEASED : RET_DHCP_ERROR; + } + } while ((len == -1) && (errno == EAGAIN)); if (iface->bTokenRing) { /* Here we convert a TR frame into an Eth frame */ @@ -752,7 +759,7 @@ int dhcp_init (dhcp_interface *iface) releaseDhcpOptions (iface); #ifdef DEBUG - fprintf(stderr,"ClassID = \"%s\"\n" + syslog (LOG_DEBUG, "ClassID = \"%s\"\n" "ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n", iface->cls_id, iface->cli_id[0], iface->cli_id[1], iface->cli_id[2], iface->cli_id[3], iface->cli_id[4], iface->cli_id[5], @@ -760,7 +767,7 @@ int dhcp_init (dhcp_interface *iface) #endif if ( DebugFlag ) - syslog (LOG_DEBUG,"broadcasting DHCP_DISCOVER\n"); + syslog (LOG_INFO, "Broadcasting DHCP_DISCOVER\n"); iface->xid = random (); err = dhcpSendAndRecv (iface, DHCP_OFFER, &buildDhcpDiscover, &msg); if (err != RET_DHCP_SUCCESS) @@ -772,7 +779,7 @@ int dhcp_init (dhcp_interface *iface) udpipMessage *msg2 = NULL; if (DebugFlag) - syslog (LOG_DEBUG,"broadcasting second DHCP_DISCOVER\n"); + syslog (LOG_INFO, "Broadcasting second DHCP_DISCOVER\n"); iface->xid = dhcp_msg->xid; err = dhcpSendAndRecv (iface, DHCP_OFFER, &buildDhcpDiscover, &msg2); @@ -792,7 +799,7 @@ int dhcp_init (dhcp_interface *iface) /* DHCP_OFFER received */ if ( DebugFlag ) { - syslog(LOG_DEBUG,"DHCP_OFFER received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, + syslog (LOG_INFO, "DHCP_OFFER received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2], @@ -814,7 +821,7 @@ int dhcp_request(dhcp_interface *iface, dhcp_msg_build_proc buildDhcpMsg) if ( DebugFlag ) { - syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", + syslog (LOG_INFO, "Broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]); } @@ -826,7 +833,7 @@ int dhcp_request(dhcp_interface *iface, dhcp_msg_build_proc buildDhcpMsg) if ( DebugFlag ) { dhcpMessage *dhcp_msg = (dhcpMessage *)&(msg->udpipmsg[sizeof(udpiphdr)]); - syslog(LOG_DEBUG, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, + syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2], @@ -840,7 +847,7 @@ int dhcp_request(dhcp_interface *iface, dhcp_msg_build_proc buildDhcpMsg) if ( arpCheck(iface) ) { if ( DebugFlag ) - syslog(LOG_DEBUG, "requested %u.%u.%u.%u address is in use\n", + syslog (LOG_INFO, "requested %u.%u.%u.%u address is in use\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]); dhcpDecline(); @@ -850,7 +857,7 @@ int dhcp_request(dhcp_interface *iface, dhcp_msg_build_proc buildDhcpMsg) if ( DebugFlag ) { - syslog(LOG_DEBUG, "verified %u.%u.%u.%u address is not in use\n", + syslog (LOG_INFO, "verified %u.%u.%u.%u address is not in use\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]); } @@ -895,7 +902,7 @@ int dhcp_renew(dhcp_interface *iface) if ( DebugFlag ) { - syslog(LOG_DEBUG,"sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n", + syslog (LOG_INFO,"Sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3], ((unsigned char *)&(iface->siaddr))[0], ((unsigned char *)&(iface->siaddr))[1], @@ -912,7 +919,7 @@ int dhcp_renew(dhcp_interface *iface) if ( DebugFlag ) { dhcpMessage *dhcp_msg = (dhcpMessage *)&(msg->udpipmsg[sizeof(udpiphdr)]); - syslog(LOG_DEBUG, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, + syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2], @@ -938,7 +945,7 @@ int dhcp_rebind(dhcp_interface *iface) if ( DebugFlag ) { - syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", + syslog (LOG_INFO,"Broadcasting DHCP_REQUEST for %u.%u.%u.%u\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], @@ -955,7 +962,7 @@ int dhcp_rebind(dhcp_interface *iface) if ( DebugFlag ) { dhcpMessage *dhcp_msg = (dhcpMessage *)&(msg->udpipmsg[sizeof(udpiphdr)]); - syslog(LOG_DEBUG, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, + syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2], @@ -984,7 +991,7 @@ int dhcp_release(dhcp_interface *iface) if (DebugFlag) { - syslog(LOG_DEBUG,"sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n", + syslog (LOG_INFO, "Sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3], ((unsigned char *)&(iface->siaddr))[0], ((unsigned char *)&(iface->siaddr))[1], @@ -994,7 +1001,7 @@ int dhcp_release(dhcp_interface *iface) memset (&addr, 0, sizeof(struct sockaddr)); memcpy (addr.sa_data, iface->iface, strlen (iface->iface)); if ( sendto (iface->sk, msg, sizeof(struct packed_ether_header) + sizeof(udpiphdr) + sizeof(dhcpMessage), 0, &addr, sizeof(struct sockaddr)) == -1 ) - syslog(LOG_ERR,"dhcpRelease: sendto: %m\n"); + syslog (LOG_ERR, "dhcpRelease: sendto: %m\n"); free (msg); arpRelease (iface); /* clear ARP cache entries for client IP addr */ @@ -1016,7 +1023,7 @@ int dhcp_decline(dhcp_interface *iface) memset (&addr, 0, sizeof(struct sockaddr)); memcpy (addr.sa_data, iface->iface, strlen (iface->iface)); if ( DebugFlag ) - syslog (LOG_DEBUG,"broadcasting DHCP_DECLINE\n"); + syslog (LOG_INFO, "Broadcasting DHCP_DECLINE\n"); if ( sendto (iface->sk, msg, sizeof(struct packed_ether_header) + sizeof(udpiphdr)+sizeof(dhcpMessage), 0, &addr, sizeof(struct sockaddr)) == -1 ) syslog (LOG_ERR,"dhcpDecline: sendto: %m\n"); @@ -1033,7 +1040,7 @@ int dhcp_inform(dhcp_interface *iface) if ( DebugFlag ) { - syslog(LOG_DEBUG, "broadcasting DHCP_INFORM for %u.%u.%u.%u\n", + syslog (LOG_INFO, "Broadcasting DHCP_INFORM for %u.%u.%u.%u\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], @@ -1048,7 +1055,7 @@ int dhcp_inform(dhcp_interface *iface) if ( DebugFlag ) { dhcpMessage *dhcp_msg = (dhcpMessage *)&(msg->udpipmsg[sizeof(udpiphdr)]); - syslog(LOG_DEBUG, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, + syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_msg->sname, ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1], ((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2], @@ -1061,7 +1068,7 @@ int dhcp_inform(dhcp_interface *iface) if ( arpCheck(iface) ) { if ( DebugFlag ) - syslog(LOG_DEBUG, "requested %u.%u.%u.%u address is in use\n", + syslog (LOG_INFO, "Requested %u.%u.%u.%u address is in use\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]); dhcpDecline (iface); @@ -1069,7 +1076,7 @@ int dhcp_inform(dhcp_interface *iface) } if ( DebugFlag ) { - syslog(LOG_DEBUG, "verified %u.%u.%u.%u address is not in use\n", + syslog (LOG_INFO, "Verified %u.%u.%u.%u address is not in use\n", ((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1], ((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]); } @@ -1095,7 +1102,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) int i,j; dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]); - fprintf (stderr,"parseDhcpMsgRecv: %d options received:\n", options->num); + syslog (LOG_INFO, "parseDhcpMsgRecv: %d options received:\n", options->num); for (i = 1; i < 255; i++) { if ( options->val[i] ) @@ -1116,7 +1123,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) for (j = 0; j < options->len[i]; j += 4) { char *opt_name = get_dhcp_option_name (i); - fprintf (stderr,"i=%-2d (%s) len=%-2d option = %u.%u.%u.%u\n", + syslog (LOG_INFO, "i=%-2d (%s) len=%-2d option = %u.%u.%u.%u\n", i, opt_name, options->len[i], ((unsigned char *)options->val[i])[0+j], ((unsigned char *)options->val[i])[1+j], @@ -1132,7 +1139,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) case 59:/* dhcpT2value */ { char *opt_name = get_dhcp_option_name (i); - fprintf (stderr,"i=%-2d (%s) len=%-2d option = %d\n", i, opt_name, + syslog (LOG_INFO, "i=%-2d (%s) len=%-2d option = %d\n", i, opt_name, options->len[i], ntohl(*(int *)options->val[i])); free (opt_name); } @@ -1143,7 +1150,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) case 53:/* dhcpMessageType */ { char *opt_name = get_dhcp_option_name (i); - fprintf(stderr,"i=%-2d (%s) len=%-2d option = %u\n", i, opt_name, + syslog (LOG_INFO, "i=%-2d (%s) len=%-2d option = %u\n", i, opt_name, options->len[i],*(unsigned char *)options->val[i]); free (opt_name); } @@ -1151,7 +1158,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) default: { char *opt_name = get_dhcp_option_name (i); - fprintf(stderr,"i=%-2d (%s) len=%-2d option = \"%s\"\n", + syslog (LOG_INFO, "i=%-2d (%s) len=%-2d option = \"%s\"\n", i, opt_name, options->len[i], (char *)options->val[i]); free (opt_name); } @@ -1160,7 +1167,7 @@ void debug_dump_dhcp_options (udpipMessage *udp_msg, dhcpOptions *options) } } - fprintf(stderr,"dhcp_msg->yiaddr = %u.%u.%u.%u\n" + syslog (LOG_INFO, "dhcp_msg->yiaddr = %u.%u.%u.%u\n" "dhcp_msg->siaddr = %u.%u.%u.%u\n" "dhcp_msg->giaddr = %u.%u.%u.%u\n" "dhcp_msg->sname = \"%s\"\n" diff --git a/dhcpcd/client.h b/dhcpcd/client.h index 4f67eeff23..1095115c08 100644 --- a/dhcpcd/client.h +++ b/dhcpcd/client.h @@ -40,7 +40,7 @@ #define HWADDR_TRIES 3 /* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 /* from client to server */ +#define DHCP_SERVER_PORT 67 /* from client to server */ #define DHCP_CLIENT_PORT 68 /* from server to client */ /* DHCP message OP code */ @@ -48,86 +48,18 @@ #define DHCP_BOOTREPLY 2 /* DHCP message type */ -#define DHCP_DISCOVER 1 +#define DHCP_DISCOVER 1 #define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 #define DHCP_NAK 6 -#define DHCP_RELEASE 7 +#define DHCP_RELEASE 7 #define DHCP_INFORM 8 /* DHCP RETRANSMISSION TIMEOUT (microseconds) */ #define DHCP_INITIAL_RTO (4*1000000) #define DHCP_MAX_RTO (64*1000000) -/* DHCP option and value (cf. RFC1533) */ -enum -{ - padOption = 0, - subnetMask = 1, - timerOffset = 2, - routersOnSubnet = 3, - timeServer = 4, - nameServer = 5, - dns = 6, - logServer = 7, - cookieServer = 8, - lprServer = 9, - impressServer = 10, - resourceLocationServer = 11, - hostName = 12, - bootFileSize = 13, - meritDumpFile = 14, - domainName = 15, - swapServer = 16, - rootPath = 17, - extentionsPath = 18, - IPforwarding = 19, - nonLocalSourceRouting = 20, - policyFilter = 21, - maxDgramReasmSize = 22, - defaultIPTTL = 23, - pathMTUagingTimeout = 24, - pathMTUplateauTable = 25, - ifMTU = 26, - allSubnetsLocal = 27, - broadcastAddr = 28, - performMaskDiscovery = 29, - maskSupplier = 30, - performRouterDiscovery = 31, - routerSolicitationAddr = 32, - staticRoute = 33, - trailerEncapsulation = 34, - arpCacheTimeout = 35, - ethernetEncapsulation = 36, - tcpDefaultTTL = 37, - tcpKeepaliveInterval = 38, - tcpKeepaliveGarbage = 39, - nisDomainName = 40, - nisServers = 41, - ntpServers = 42, - vendorSpecificInfo = 43, - netBIOSnameServer = 44, - netBIOSdgramDistServer = 45, - netBIOSnodeType = 46, - netBIOSscope = 47, - xFontServer = 48, - xDisplayManager = 49, - dhcpRequestedIPaddr = 50, - dhcpIPaddrLeaseTime = 51, - dhcpOptionOverload = 52, - dhcpMessageType = 53, - dhcpServerIdentifier = 54, - dhcpParamRequest = 55, - dhcpMsg = 56, - dhcpMaxMsgSize = 57, - dhcpT1value = 58, - dhcpT2value = 59, - dhcpClassIdentifier = 60, - dhcpClientIdentifier = 61, - endOption = 255 -}; - typedef struct dhcpMessage { u_char op; /* message type */ diff --git a/dhcpcd/dhcpcd.c b/dhcpcd/dhcpcd.c index 01c6086085..2193953881 100644 --- a/dhcpcd/dhcpcd.c +++ b/dhcpcd/dhcpcd.c @@ -119,7 +119,7 @@ dhcp_interface *dhcp_interface_init (const char *if_name, dhcp_client_options *i memcpy (sap.spkt_device, iface->iface, strlen (iface->iface)); sap.spkt_family = AF_PACKET; if ( bind (iface->sk, (void*)&sap, sizeof(struct sockaddr)) == -1 ) - syslog (LOG_ERR,"dhcp_interface_init: bind: %m\n"); + syslog (LOG_ERR,"dhcp_interface_init: bind: %m\n"); memcpy (iface->chaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); fprintf(stdout,"dhcpcd: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -168,6 +168,9 @@ void dhcp_interface_free (dhcp_interface *iface) struct ifreq ifr; struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr); + if (!iface) + return; + releaseDhcpOptions (iface); if (iface->foo_sk >= 0) diff --git a/dhcpcd/dhcpcd.h b/dhcpcd/dhcpcd.h index 4945783e74..b81316e23d 100644 --- a/dhcpcd/dhcpcd.h +++ b/dhcpcd/dhcpcd.h @@ -31,6 +31,73 @@ #define DHCP_CLIENT_ID_MAX_LEN 48 #define DHCP_HOSTNAME_MAX_LEN 64 +/* DHCP option and value (cf. RFC1533) */ +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + timeServer = 4, + nameServer = 5, + dns = 6, + logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11, + hostName = 12, + bootFileSize = 13, + meritDumpFile = 14, + domainName = 15, + swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49, + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + dhcpOptionOverload = 52, + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + dhcpMsg = 56, + dhcpMaxMsgSize = 57, + dhcpT1value = 58, + dhcpT2value = 59, + dhcpClassIdentifier = 60, + dhcpClientIdentifier = 61, + endOption = 255 +}; /* Return codes */ #define RET_DHCP_ERROR 0 diff --git a/src/NetworkManagerDHCP.c b/src/NetworkManagerDHCP.c index 1a40cfe0e4..986efcaf59 100644 --- a/src/NetworkManagerDHCP.c +++ b/src/NetworkManagerDHCP.c @@ -23,81 +23,98 @@ #include #include #include +#include #include "NetworkManager.h" #include "NetworkManagerMain.h" #include "NetworkManagerDevice.h" +#include "NetworkManagerDevicePrivate.h" #include "NetworkManagerDHCP.h" #include "NetworkManagerSystem.h" #include "../dhcpcd/client.h" -/* Accessors to device data that only this file should need */ -dhcp_interface *nm_device_get_dhcp_iface (NMDevice *dev); -void nm_device_set_dhcp_iface (NMDevice *dev, dhcp_interface *dhcp_iface); + +/* + * nm_device_dhcp_configure + * + * Using the results of a DHCP request, configure the device. + * + */ +static void nm_device_dhcp_configure (NMDevice *dev) +{ + int temp; + + g_return_if_fail (dev != NULL); + g_return_if_fail (dev->dhcp_iface != NULL); + + /* Replace basic info */ + nm_system_device_set_ip4_address (dev, dev->dhcp_iface->ciaddr); + + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, subnetMask)) + { + memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, subnetMask), dhcp_individual_value_len (subnetMask)); + nm_system_device_set_ip4_netmask (dev, temp); + } + + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, subnetMask)) + { + memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, broadcastAddr), dhcp_individual_value_len (broadcastAddr)); + nm_system_device_set_ip4_broadcast (dev, temp); + } + + /* Default route */ + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, routersOnSubnet)) + { + memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, routersOnSubnet), dhcp_individual_value_len (routersOnSubnet)); + nm_system_device_set_ip4_default_route (dev, temp); + } + + /* Update /etc/resolv.conf */ + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dns)) + { + nm_system_device_update_resolv_conf (dhcp_interface_get_dhcp_field (dev->dhcp_iface, dns), + dhcp_interface_get_dhcp_field_len (dev->dhcp_iface, dns), dhcp_interface_get_dhcp_field (dev->dhcp_iface, domainName)); + } +} /* - * nm_device_dhcp_run + * nm_device_dhcp_request * * Start a DHCP transaction on particular device. * */ -int nm_device_dhcp_run (NMDevice *dev) +int nm_device_dhcp_request (NMDevice *dev) { - dhcp_interface *dhcp_iface; dhcp_client_options opts; int err; - const char *iface; g_return_val_if_fail (dev != NULL, RET_DHCP_ERROR); + if (dev->dhcp_iface) + { + syslog (LOG_ERR, "nm_device_dhcp_request(): device DHCP info exists, but it should have been cleared already.\n"); + dhcp_interface_free (dev->dhcp_iface); + } + memset (&opts, 0, sizeof (dhcp_client_options)); opts.base_timeout = 30; - - iface = nm_device_get_iface (dev); - if (!(dhcp_iface = dhcp_interface_init (iface, &opts))) + if (!(dev->dhcp_iface = dhcp_interface_init (nm_device_get_iface (dev), &opts))) return RET_DHCP_ERROR; - nm_device_set_dhcp_iface (dev, dhcp_iface); /* Start off in DHCP INIT state, get a completely new IP address * and settings. */ - err = dhcp_init (dhcp_iface); - if (err == RET_DHCP_BOUND) + if ((err = dhcp_init (dev->dhcp_iface)) == RET_DHCP_BOUND) { - int temp; - - /* Replace basic info */ - nm_system_device_set_ip4_address (dev, dhcp_iface->ciaddr); - - if (dhcp_interface_dhcp_field_exists (dhcp_iface, subnetMask)) - { - memcpy (&temp, dhcp_interface_get_dhcp_field (dhcp_iface, subnetMask), dhcp_individual_value_len (subnetMask)); - nm_system_device_set_ip4_netmask (dev, temp); - } - - if (dhcp_interface_dhcp_field_exists (dhcp_iface, subnetMask)) - { - memcpy (&temp, dhcp_interface_get_dhcp_field (dhcp_iface, broadcastAddr), dhcp_individual_value_len (broadcastAddr)); - nm_system_device_set_ip4_broadcast (dev, temp); - } - - /* Default route */ - if (dhcp_interface_dhcp_field_exists (dhcp_iface, routersOnSubnet)) - { - memcpy (&temp, dhcp_interface_get_dhcp_field (dhcp_iface, routersOnSubnet), dhcp_individual_value_len (routersOnSubnet)); - nm_system_device_set_ip4_default_route (dev, temp); - } - - /* Update /etc/resolv.conf */ - if (dhcp_interface_dhcp_field_exists (dhcp_iface, dns)) - { - nm_system_device_update_resolv_conf (dhcp_interface_get_dhcp_field (dhcp_iface, dns), - dhcp_interface_get_dhcp_field_len (dhcp_iface, dns), dhcp_interface_get_dhcp_field (dhcp_iface, domainName)); - } + nm_device_dhcp_configure (dev); + nm_device_update_ip4_address (dev); + nm_device_dhcp_setup_timeouts (dev); + } + else + { + dhcp_interface_free (dev->dhcp_iface); + dev->dhcp_iface = NULL; } - - dhcp_interface_free (dhcp_iface); - nm_device_set_dhcp_iface (dev, NULL); return (err); } @@ -112,8 +129,129 @@ int nm_device_dhcp_run (NMDevice *dev) void nm_device_dhcp_cease (NMDevice *dev) { g_return_if_fail (dev != NULL); - g_return_if_fail (nm_device_get_dhcp_iface (dev) != NULL); + g_return_if_fail (dev->dhcp_iface != NULL); - dhcp_interface_cease (nm_device_get_dhcp_iface (dev)); + dhcp_interface_cease (dev->dhcp_iface); +} + + +/* + * nm_device_dhcp_setup_timeouts + * + * Set up the DHCP renew and rebind timeouts for a device. + * + * Returns: FALSE on error + * TRUE on success + * + */ +gboolean nm_device_dhcp_setup_timeouts (NMDevice *dev) +{ + int t1 = 0, t2 = 0; + GSource *t1_source, *t2_source; + + g_return_val_if_fail (dev != NULL, FALSE); + + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dhcpT1value)) + { + memcpy (&t1, dhcp_interface_get_dhcp_field (dev->dhcp_iface, dhcpT1value), sizeof (int)); + t1 = ntohl (t1); + } + if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dhcpT2value)) + { + memcpy (&t2, dhcp_interface_get_dhcp_field (dev->dhcp_iface, dhcpT2value), sizeof (int)); + t2 = ntohl (t2); + } + if (!t1 || !t2) + { + syslog (LOG_ERR, "DHCP renew/rebind values were 0! Won't renew lease."); + return (FALSE); + } + + t1_source = g_timeout_source_new (t1 * 1000); + t2_source = g_timeout_source_new (t2 * 1000); + g_source_set_callback (t1_source, nm_device_dhcp_renew, dev, NULL); + g_source_set_callback (t2_source, nm_device_dhcp_rebind, dev, NULL); + dev->renew_timeout = g_source_attach (t1_source, dev->context); + dev->rebind_timeout = g_source_attach (t2_source, dev->context); + + return (TRUE); +} + + +/* + * nm_device_dhcp_renew + * + * Renew a DHCP address. + * + */ +gboolean nm_device_dhcp_renew (gpointer user_data) +{ + NMDevice *dev = (NMDevice *)user_data; + + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (dev->app_data != NULL, FALSE); + g_return_val_if_fail (dev->dhcp_iface, FALSE); + + if (dhcp_renew (dev->dhcp_iface) != RET_DHCP_BOUND) + { + /* If the T1 renewal fails, then we wait around until T2 + * for rebind. + */ + return (FALSE); + } + else + { + /* Lease renewed, start timers again from 0 */ + nm_device_dhcp_setup_timeouts (dev); + } + + /* Always return false to remove ourselves, since we just + * set up another timeout above. + */ + return (FALSE); +} + + +/* + * nm_device_dhcp_renew + * + * Renew a DHCP address. + * + */ +gboolean nm_device_dhcp_rebind (gpointer user_data) +{ + NMDevice *dev = (NMDevice *)user_data; + + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (dev->app_data != NULL, FALSE); + g_return_val_if_fail (dev->dhcp_iface, FALSE); + + if (dhcp_rebind (dev->dhcp_iface) != RET_DHCP_BOUND) + { + /* T2 rebind failed, so flush the device's address and signal + * that we should find another device to use. + */ + /* FIXME: technically we should run out the entire lease time before + * flushing the address and getting a new device. We'll leave that for + * a bit later (do a new timer for entire lease time, blah, blah). + */ + nm_system_device_flush_addresses (dev); + nm_device_update_ip4_address (dev); + nm_data_mark_state_changed (dev->app_data); + return (FALSE); + } + else + { + /* Lease renewed, start timers again from 0 */ + nm_device_dhcp_setup_timeouts (dev); + } + + dhcp_interface_free (dev->dhcp_iface); + dev->dhcp_iface = NULL; + + /* Always return false to remove ourselves, since we just + * set up another timeout above. + */ + return (FALSE); } diff --git a/src/NetworkManagerDHCP.h b/src/NetworkManagerDHCP.h index 4a06267975..57dc7779ee 100644 --- a/src/NetworkManagerDHCP.h +++ b/src/NetworkManagerDHCP.h @@ -24,8 +24,10 @@ #include "../dhcpcd/dhcpcd.h" - -int nm_device_dhcp_run (NMDevice *dev); +int nm_device_dhcp_request (NMDevice *dev); void nm_device_dhcp_cease (NMDevice *dev); +gboolean nm_device_dhcp_setup_timeouts (NMDevice *dev); +gboolean nm_device_dhcp_renew (gpointer user_data); +gboolean nm_device_dhcp_rebind (gpointer user_data); #endif diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index a5171da655..dde3930342 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -30,6 +30,7 @@ #include "NetworkManager.h" #include "NetworkManagerMain.h" #include "NetworkManagerDevice.h" +#include "NetworkManagerDevicePrivate.h" #include "NetworkManagerUtils.h" #include "NetworkManagerDbus.h" #include "NetworkManagerWireless.h" @@ -46,88 +47,6 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev); /******************************************************/ -/* Wireless device specific options */ -typedef struct NMDeviceWirelessOptions -{ - char *cur_essid; - gboolean supports_wireless_scan; - guint8 max_quality; - guint8 noise; - gint8 strength; - gint8 invalid_strength_counter; - - GMutex *scan_mutex; - /* We keep a couple lists around since wireless cards - * are a bit flakey and don't report the same access - * points every time. The lists get merged and diffed - * to figure out the "real" list, but the latest_ap_list - * is always the most-current scan. - */ - NMAccessPointList *ap_list; - NMAccessPointList *cached_ap_list1; - NMAccessPointList *cached_ap_list2; - NMAccessPointList *cached_ap_list3; - - NMAccessPoint *best_ap; - GMutex *best_ap_mutex; - gboolean freeze_best_ap; - - gboolean user_key_received; - gboolean now_scanning; -} NMDeviceWirelessOptions; - -/* Wired device specific options */ -typedef struct NMDeviceWiredOptions -{ - int foo; -} NMDeviceWiredOptions; - -typedef union NMDeviceOptions -{ - NMDeviceWirelessOptions wireless; - NMDeviceWiredOptions wired; -} NMDeviceOptions; - - -typedef struct NMDeviceConfigInfo -{ - gboolean use_dhcp; - guint32 ip4_gateway; - guint32 ip4_address; - guint32 ip4_netmask; - guint32 ip4_broadcast; - /* FIXME: ip6 stuff */ -} NMDeviceConfigInfo; - -/* - * NetworkManager device structure - */ -struct NMDevice -{ - guint refcount; - - char *udi; - char *iface; - NMDeviceType type; - NMDriverSupportLevel driver_support_level; - - gboolean link_active; - guint32 ip4_address; - /* FIXME: ipv6 address too */ - unsigned char hw_addr[ETH_ALEN]; - NMData *app_data; - NMDeviceOptions options; - NMDeviceConfigInfo config_info; - struct dhcp_interface *dhcp_iface; - - gboolean activating; /* Set by main thread before beginning activation */ - gboolean just_activated; /* Set by activation thread after successful activation */ - gboolean quit_activation; /* Flag to signal activation thread to stop activating */ - gboolean activation_failed; /* Did the activation fail? */ - - gboolean test_device; - gboolean test_device_up; -}; /******************************************************/ @@ -1564,6 +1483,10 @@ get_ap: { int ip_success = FALSE; + /* If we were told to quit activation, stop the thread and return */ + if (nm_device_activation_should_cancel (dev)) + goto out; + nm_device_set_wireless_config (dev, best_ap, auth); if (!HAVE_LINK (dev) && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) { @@ -1640,7 +1563,7 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev) { int err; - err = nm_device_dhcp_run (dev); + err = nm_device_dhcp_request (dev); if (err == RET_DHCP_BOUND) success = TRUE; else @@ -1679,6 +1602,7 @@ static gpointer nm_device_activation_worker (gpointer user_data) { NMDevice *dev = (NMDevice *)user_data; gboolean success = FALSE; + GMainContext *context = NULL; g_return_val_if_fail (dev != NULL, NULL); g_return_val_if_fail (dev->app_data != NULL, NULL); @@ -1712,10 +1636,31 @@ static gpointer nm_device_activation_worker (gpointer user_data) dev->activation_failed = FALSE; dev->quit_activation = FALSE; + /* If we were told to quit activation, stop the thread and return */ + if (nm_device_activation_should_cancel (dev)) + goto out; + nm_device_update_ip4_address (dev); syslog (LOG_DEBUG, "nm_device_activation_worker(%s): device activated", nm_device_get_iface (dev)); + if (!nm_device_config_get_use_dhcp (dev) || !dev->dhcp_iface) + goto out; + + /* We stick around if we need to renew the address with DHCP or something. */ + dev->context = g_main_context_new (); + dev->loop = g_main_loop_new (context, FALSE); + nm_device_dhcp_setup_timeouts (dev); + + g_main_loop_run (dev->loop); + + g_source_remove (dev->renew_timeout); + g_source_remove (dev->rebind_timeout); + g_main_loop_unref (dev->loop); + g_main_context_unref (dev->context); + dev->context = NULL; + dev->loop = NULL; + out: nm_device_unref (dev); return (NULL); @@ -1820,6 +1765,9 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) nm_device_activation_cancel (dev); + if (dev->loop) + g_main_loop_quit (dev->loop); + if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED) return (TRUE); @@ -2279,9 +2227,10 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, *encrypted = FALSE; - /* Force the card into Managed/Infrastructure mode */ nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC); + g_usleep (G_USEC_PER_SEC * 4); + + /* Force the card into Managed/Infrastructure mode */ nm_device_set_mode_managed (dev); if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), network)) && !nm_ap_get_encrypted (ap)) @@ -2337,7 +2286,7 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, /* Bring the device up and pause to allow card to associate */ nm_device_set_essid (dev, network); - g_usleep (G_USEC_PER_SEC * 2); + g_usleep (G_USEC_PER_SEC * 3); nm_device_update_link_active (dev, FALSE); nm_device_get_ap_address (dev, &addr); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h new file mode 100644 index 0000000000..2ad22ff62b --- /dev/null +++ b/src/NetworkManagerDevicePrivate.h @@ -0,0 +1,123 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2004 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "NetworkManager.h" +#include "NetworkManagerMain.h" +#include "NetworkManagerDevice.h" +#include "NetworkManagerAPList.h" + + +/* Wireless device specific options */ +typedef struct NMDeviceWirelessOptions +{ + char *cur_essid; + gboolean supports_wireless_scan; + guint8 max_quality; + guint8 noise; + gint8 strength; + gint8 invalid_strength_counter; + + GMutex *scan_mutex; + /* We keep a couple lists around since wireless cards + * are a bit flakey and don't report the same access + * points every time. The lists get merged and diffed + * to figure out the "real" list, but the latest_ap_list + * is always the most-current scan. + */ + NMAccessPointList *ap_list; + NMAccessPointList *cached_ap_list1; + NMAccessPointList *cached_ap_list2; + NMAccessPointList *cached_ap_list3; + + NMAccessPoint *best_ap; + GMutex *best_ap_mutex; + gboolean freeze_best_ap; + + gboolean user_key_received; + gboolean now_scanning; +} NMDeviceWirelessOptions; + +/* Wired device specific options */ +typedef struct NMDeviceWiredOptions +{ + int foo; +} NMDeviceWiredOptions; + +typedef union NMDeviceOptions +{ + NMDeviceWirelessOptions wireless; + NMDeviceWiredOptions wired; +} NMDeviceOptions; + + +typedef struct NMDeviceConfigInfo +{ + gboolean use_dhcp; + guint32 ip4_gateway; + guint32 ip4_address; + guint32 ip4_netmask; + guint32 ip4_broadcast; + /* FIXME: ip6 stuff */ +} NMDeviceConfigInfo; + +/* + * NetworkManager device structure + */ +struct NMDevice +{ + guint refcount; + + char *udi; + char *iface; + NMDeviceType type; + NMDriverSupportLevel driver_support_level; + + gboolean link_active; + guint32 ip4_address; + /* FIXME: ipv6 address too */ + unsigned char hw_addr[ETH_ALEN]; + NMData *app_data; + NMDeviceOptions options; + NMDeviceConfigInfo config_info; + struct dhcp_interface *dhcp_iface; + + GMainContext *context; + GMainLoop *loop; + guint renew_timeout; + guint rebind_timeout; + + gboolean activating; /* Set by main thread before beginning activation */ + gboolean just_activated; /* Set by activation thread after successful activation */ + gboolean quit_activation; /* Flag to signal activation thread to stop activating */ + gboolean activation_failed; /* Did the activation fail? */ + + gboolean test_device; + gboolean test_device_up; +}; + diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index c6743e056f..aa473cdb90 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -289,9 +289,9 @@ gboolean nm_state_modification_monitor (gpointer user_data) syslog (LOG_INFO, " SWITCH: best device changed"); do_switch = TRUE; /* Device changed */ } - else if (best_dev && nm_device_is_wireless (best_dev)) + else if (best_dev) { - if (!nm_device_is_activating (best_dev) && nm_device_need_ap_switch (best_dev)) + if (nm_device_is_wireless (best_dev) && !nm_device_is_activating (best_dev) && nm_device_need_ap_switch (best_dev)) { syslog (LOG_INFO, " SWITCH: need to associate with new access point"); do_switch = TRUE; diff --git a/src/NetworkManagerWireless.c b/src/NetworkManagerWireless.c index 763f3caf05..6967247ab2 100644 --- a/src/NetworkManagerWireless.c +++ b/src/NetworkManagerWireless.c @@ -143,6 +143,13 @@ int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual) /* Atmel driver seems to use qual->qual is the percentage value */ percent = CLAMP (qual->qual, 0, 100); } + else if (qual->qual == (qual->level - qual->noise)) + { + /* Ok, simple signal : noise ratio. Prism54 for example. */ +//fprintf (stderr, "20 * log (level / noise) = 20 * log (%d / %d) = %f\n", qual->level, qual->noise, log ((255-qual->level) / (255-qual->noise)) * 100); + percent = (int)rint ((log (qual->qual) / log (96)) * 100.0); + percent = CLAMP (percent, 0, 100); + } else if (qual->qual >= 1) { /* Try it the Gnome Wireless Applet way */