/* Add our classless static routes to the routes variable * and return the last route set */ static route_t *decode_CSR(const unsigned char *p, int len) { const unsigned char *q = p; int cidr; int ocets; route_t *first; route_t *route; /* Minimum is 5 -first is CIDR and a router length of 4 */ if (len < 5) return NULL; first = xmalloc (sizeof (route_t)); route = first; while (q - p < len) { memset (route, 0, sizeof (route_t)); cidr = *q++; if (cidr > 32) { logger (LOG_ERR, "invalid CIDR of %d in classless static route", cidr); free_route (first); return (NULL); } ocets = (cidr + 7) / 8; if (ocets > 0) { memcpy (&route->destination.s_addr, q, ocets); q += ocets; } /* Now enter the netmask */ if (ocets > 0) { memset (&route->netmask.s_addr, 255, ocets - 1); memset ((unsigned char *) &route->netmask.s_addr + (ocets - 1), (256 - (1 << (32 - cidr) % 8)), 1); } /* Finally, snag the router */ memcpy (&route->gateway.s_addr, q, 4); q += 4; /* We have another route */ if (q - p < len) { route->next = xmalloc (sizeof (route_t)); route = route->next; } } return first; }
void free_dhcp (dhcp_t *dhcp) { if (! dhcp) return; free_route (dhcp->routes); free (dhcp->hostname); free_address (dhcp->dnsservers); free (dhcp->dnsdomain); free (dhcp->dnssearch); free_address (dhcp->ntpservers); free (dhcp->nisdomain); free_address (dhcp->nisservers); free (dhcp->rootpath); if (dhcp->fqdn) { free (dhcp->fqdn->name); free (dhcp->fqdn); } }
int handle_rtm_newroute(const struct nlmsghdr *nl){ const struct rtmsg *rt = NLMSG_DATA(nl); struct rtattr *ra; void *as,*ad,*ag; int rlen,oif; route *r,**prev; size_t flen; oif = -1; if((r = create_route()) == NULL){ return -1; } switch( (r->family = rt->rtm_family) ){ case AF_INET:{ flen = sizeof(uint32_t); as = &((struct sockaddr_in *)&r->sss)->sin_addr; ad = &((struct sockaddr_in *)&r->ssd)->sin_addr; ag = &((struct sockaddr_in *)&r->ssg)->sin_addr; break;}case AF_INET6:{ flen = sizeof(uint32_t) * 4; as = &((struct sockaddr_in6 *)&r->sss)->sin6_addr; ad = &((struct sockaddr_in6 *)&r->ssd)->sin6_addr; ag = &((struct sockaddr_in6 *)&r->ssg)->sin6_addr; break;}case AF_BRIDGE:{ // FIXME wtf is a bridge route diagnostic("got a bridge route hrmmm FIXME"); return -1; // FIXME break;}default:{ flen = 0; break;} } r->maskbits = rt->rtm_dst_len; if(flen == 0 || flen > sizeof(r->sss.__ss_padding)){ diagnostic("Unknown route family %u",rt->rtm_family); return -1; } rlen = nl->nlmsg_len - NLMSG_LENGTH(sizeof(*rt)); ra = (struct rtattr *)((char *)(NLMSG_DATA(nl)) + sizeof(*rt)); memset(&r->ssg,0,sizeof(r->ssg)); memset(&r->ssd,0,sizeof(r->ssd)); memset(&r->sss,0,sizeof(r->sss)); while(RTA_OK(ra,rlen)){ switch(ra->rta_type){ case RTA_DST:{ if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu dst bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->ssd.ss_family){ diagnostic("Got two destinations for route"); break; } memcpy(ad,RTA_DATA(ra),flen); r->ssd.ss_family = r->family; break;}case RTA_PREFSRC: case RTA_SRC:{ // FIXME do we not want to prefer PREFSRC? if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu src bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->sss.ss_family){ diagnostic("Got two sources for route"); break; } memcpy(as,RTA_DATA(ra),flen); r->sss.ss_family = r->family; break;}case RTA_IIF:{ if(RTA_PAYLOAD(ra) != sizeof(int)){ diagnostic("Expected %zu iiface bytes, got %zu", sizeof(int),RTA_PAYLOAD(ra)); break; } // we don't use RTA_OIF: iif = *(int *)RTA_DATA(ra); break;}case RTA_OIF:{ if(RTA_PAYLOAD(ra) != sizeof(int)){ diagnostic("Expected %zu oiface bytes, got %zu", sizeof(int),RTA_PAYLOAD(ra)); break; } oif = *(int *)RTA_DATA(ra); break;}case RTA_GATEWAY:{ if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu gw bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->ssg.ss_family){ diagnostic("Got two gateways for route"); break; } // We get 0.0.0.0 as the gateway when there's no 'via' if(memcmp(ag,RTA_DATA(ra),flen)){ memcpy(ag,RTA_DATA(ra),flen); r->ssg.ss_family = r->family; } break;}case RTA_PRIORITY:{ break;}case RTA_METRICS:{ break;}case RTA_MULTIPATH:{ // break;}case RTA_PROTOINFO:{ // unused break;}case RTA_FLOW:{ break;}case RTA_CACHEINFO:{ // break;}case RTA_SESSION:{ // unused // break;}case RTA_MP_ALGO:{ // unused break;}case RTA_TABLE:{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) break;}case RTA_MARK:{ #endif break;}case RTA_MFC_STATS:{ break;}case RTA_VIA:{ break;}case RTA_NEWDST:{ break;}case RTA_PREF:{ break;}case RTA_ENCAP_TYPE:{ break;}case RTA_ENCAP:{ break;}case RTA_EXPIRES:{ break;}case RTA_PAD:{ break;}default:{ diagnostic("Unknown rtatype %u",ra->rta_type); break;}} ra = RTA_NEXT(ra,rlen); } if(rlen){ diagnostic("%d excess bytes on newlink message",rlen); } if((r->iface = iface_by_idx(oif)) == NULL){ diagnostic("Unknown output interface %d on %s",oif,r->iface->name); goto err; } { char str[INET6_ADDRSTRLEN],via[INET6_ADDRSTRLEN]; inet_ntop(rt->rtm_family,ad,str,sizeof(str)); inet_ntop(rt->rtm_family,ag,via,sizeof(via)); diagnostic("[%s] new route to %s/%u %ls%ls%s", r->iface->name,str,r->maskbits, rt->rtm_type == RTN_LOCAL ? L"(local)" : rt->rtm_type == RTN_BROADCAST ? L"(broadcast)" : rt->rtm_type == RTN_UNREACHABLE ? L"(unreachable)" : rt->rtm_type == RTN_ANYCAST ? L"(anycast)" : rt->rtm_type == RTN_UNICAST ? L"(unicast)" : rt->rtm_type == RTN_MULTICAST ? L"(multicast)" : rt->rtm_type == RTN_BLACKHOLE ? L"(blackhole)" : rt->rtm_type == RTN_MULTICAST ? L"(multicast)" : L"", r->ssg.ss_family ? L" via " : L"", r->ssg.ss_family ? via : ""); } // We're not interest in blackholes, unreachables, prohibits, NATs yet if(rt->rtm_type != RTN_UNICAST && rt->rtm_type != RTN_LOCAL && rt->rtm_type != RTN_BROADCAST && rt->rtm_type != RTN_ANYCAST && rt->rtm_type != RTN_MULTICAST){ free_route(r); return 0; } assert(r->iface); if(!r->sss.ss_family){ struct routepath rp; if(get_router(r->sss.ss_family,ad,&rp) == 0){ if(r->sss.ss_family == AF_INET){ memcpy(as,rp.src,4); }else if(r->sss.ss_family == AF_INET6){ memcpy(as,rp.src,16); }else{ assert(0); } }else{ // FIXME vicious hackery! if(r->family == AF_INET6){ memcpy(as,r->iface->ip6defsrc,flen); r->sss.ss_family = AF_INET6; } } } if(r->family == AF_INET){ lock_interface(r->iface); if(add_route4(r->iface,ad,r->ssg.ss_family ? ag : NULL, r->sss.ss_family ? as : NULL, r->maskbits)){ unlock_interface(r->iface); diagnostic("Couldn't add route to %s",r->iface->name); goto err; } if(r->ssg.ss_family){ send_arp_req(r->iface,r->iface->bcast,ag,as); } unlock_interface(r->iface); pthread_mutex_lock(&route_lock); prev = &ip_table4; // Order most-specific (largest maskbits) to least-specific (0 maskbits) while(*prev){ if(r->maskbits > (*prev)->maskbits){ break; } prev = &(*prev)->next; } r->next = *prev; *prev = r; if(r->sss.ss_family){ while( *(prev = &(*prev)->next) ){ assert((*prev)->maskbits < r->maskbits); if(!((*prev)->sss.ss_family)){ memcpy(&(*prev)->sss,&r->sss,sizeof(r->sss)); } } } pthread_mutex_unlock(&route_lock); }else if(r->family == AF_INET6){ lock_interface(r->iface); if(add_route6(r->iface,ad,r->ssg.ss_family ? ag : NULL,r->sss.ss_family ? as : NULL,r->maskbits)){ unlock_interface(r->iface); diagnostic("Couldn't add route to %s",r->iface->name); goto err; } unlock_interface(r->iface); pthread_mutex_lock(&route_lock); prev = &ip_table6; // Order most-specific (largest maskbits) to least-specific (0 maskbits) while(*prev){ if(r->maskbits > (*prev)->maskbits){ break; } prev = &(*prev)->next; } r->next = *prev; *prev = r; // FIXME set less-specific sources pthread_mutex_unlock(&route_lock); } return 0; err: free_route(r); return -1; }
int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) { const unsigned char *p = message->options; const unsigned char *end = p; /* Add size later for gcc-3 issue */ unsigned char option; unsigned char length; unsigned int len = 0; int i; int retval = -1; route_t *routers = NULL; route_t *routersp = NULL; route_t *static_routes = NULL; route_t *static_routesp = NULL; route_t *csr = NULL; end += sizeof (message->options); dhcp->address.s_addr = message->yiaddr; strlcpy (dhcp->servername, message->servername, sizeof (dhcp->servername)); #define LEN_ERR \ { \ logger (LOG_ERR, "invalid length %d for option %d", length, option); \ p += length; \ continue; \ } while (p < end) { option = *p++; if (! option) continue; length = *p++; if (p + length >= end) { logger (LOG_ERR, "dhcp option exceeds message length"); retval = -1; goto eexit; } switch (option) { case DHCP_END: goto eexit; case DHCP_MESSAGETYPE: retval = (int) *p; p += length; continue; default: if (length == 0) { logger (LOG_DEBUG, "option %d has zero length, skipping", option); continue; } } #define LENGTH(_length) \ if (length != _length) \ LEN_ERR; #define MIN_LENGTH(_length) \ if (length < _length) \ LEN_ERR; #define MULT_LENGTH(_mult) \ if (length % _mult != 0) \ LEN_ERR; #define GET_UINT8(_val) \ LENGTH (sizeof (uint8_t)); \ memcpy (&_val, p, sizeof (uint8_t)); #define GET_UINT16(_val) \ LENGTH (sizeof (uint16_t)); \ memcpy (&_val, p, sizeof (uint16_t)); #define GET_UINT32(_val) \ LENGTH (sizeof (uint32_t)); \ memcpy (&_val, p, sizeof (uint32_t)); #define GET_UINT16_H(_val) \ GET_UINT16 (_val); \ _val = ntohs (_val); #define GET_UINT32_H(_val) \ GET_UINT32 (_val); \ _val = ntohl (_val); switch (option) { case DHCP_ADDRESS: GET_UINT32 (dhcp->address.s_addr); break; case DHCP_NETMASK: GET_UINT32 (dhcp->netmask.s_addr); break; case DHCP_BROADCAST: GET_UINT32 (dhcp->broadcast.s_addr); break; case DHCP_SERVERIDENTIFIER: GET_UINT32 (dhcp->serveraddress.s_addr); break; case DHCP_LEASETIME: GET_UINT32_H (dhcp->leasetime); break; case DHCP_RENEWALTIME: GET_UINT32_H (dhcp->renewaltime); break; case DHCP_REBINDTIME: GET_UINT32_H (dhcp->rebindtime); break; case DHCP_MTU: GET_UINT16_H (dhcp->mtu); /* Minimum legal mtu is 68 accoridng to RFC 2132. In practise it's 576 (minimum maximum message size) */ if (dhcp->mtu < MTU_MIN) { logger (LOG_DEBUG, "MTU %d is too low, minimum is %d; ignoring", dhcp->mtu, MTU_MIN); dhcp->mtu = 0; } break; #undef GET_UINT32_H #undef GET_UINT32 #undef GET_UINT16_H #undef GET_UINT16 #undef GET_UINT8 #define GETSTR(_var) \ MIN_LENGTH (sizeof (char)); \ if (_var) free (_var); \ _var = xmalloc (length + 1); \ memcpy (_var, p, length); \ memset (_var + length, 0, 1); case DHCP_HOSTNAME: GETSTR (dhcp->hostname); break; case DHCP_DNSDOMAIN: GETSTR (dhcp->dnsdomain); break; case DHCP_MESSAGE: GETSTR (dhcp->message); break; case DHCP_ROOTPATH: GETSTR (dhcp->rootpath); break; case DHCP_NISDOMAIN: GETSTR (dhcp->nisdomain); break; #undef GETSTR #define GETADDR(_var) \ MULT_LENGTH (4); \ if (! dhcp_add_address (&_var, p, length)) \ { \ retval = -1; \ goto eexit; \ } case DHCP_DNSSERVER: GETADDR (dhcp->dnsservers); break; case DHCP_NTPSERVER: GETADDR (dhcp->ntpservers); break; case DHCP_NISSERVER: GETADDR (dhcp->nisservers); break; #undef GETADDR case DHCP_DNSSEARCH: MIN_LENGTH (1); free (dhcp->dnssearch); if ((len = decode_search (p, length, NULL)) > 0) { dhcp->dnssearch = xmalloc (len); decode_search (p, length, dhcp->dnssearch); } break; case DHCP_CSR: MIN_LENGTH (5); free_route (csr); csr = decodeCSR (p, length); break; case DHCP_STATICROUTE: MULT_LENGTH (8); for (i = 0; i < length; i += 8) { if (static_routesp) { static_routesp->next = xmalloc (sizeof (route_t)); static_routesp = static_routesp->next; } else static_routesp = static_routes = xmalloc (sizeof (route_t)); memset (static_routesp, 0, sizeof (route_t)); memcpy (&static_routesp->destination.s_addr, p + i, 4); memcpy (&static_routesp->gateway.s_addr, p + i + 4, 4); static_routesp->netmask.s_addr = getnetmask (static_routesp->destination.s_addr); } break; case DHCP_ROUTERS: MULT_LENGTH (4); for (i = 0; i < length; i += 4) { if (routersp) { routersp->next = xmalloc (sizeof (route_t)); routersp = routersp->next; } else routersp = routers = xmalloc (sizeof (route_t)); memset (routersp, 0, sizeof (route_t)); memcpy (&routersp->gateway.s_addr, p + i, 4); } break; #undef LENGTH #undef MIN_LENGTH #undef MULT_LENGTH default: logger (LOG_DEBUG, "no facility to parse DHCP code %u", option); break; } p += length; } eexit: /* Fill in any missing fields */ if (! dhcp->netmask.s_addr) dhcp->netmask.s_addr = getnetmask (dhcp->address.s_addr); if (! dhcp->broadcast.s_addr) dhcp->broadcast.s_addr = dhcp->address.s_addr | ~dhcp->netmask.s_addr; /* If we have classess static routes then we discard static routes and routers according to RFC 3442 */ if (csr) { dhcp->routes = csr; free_route (routers); free_route (static_routes); } else { /* Ensure that we apply static routes before routers */ if (static_routes) { dhcp->routes = static_routes; static_routesp->next = routers; } else dhcp->routes = routers; } return retval; }
int parse_dhcpmessage (dhcp_t *dhcp, dhcpmessage_t *message) { unsigned char *p = message->options; unsigned char option; unsigned char length; unsigned char *end = message->options + sizeof (message->options); unsigned int len = 0; int i; int retval = -1; route_t *first_route = xmalloc (sizeof (route_t)); route_t *route = first_route; route_t *last_route = NULL; route_t *csr = NULL; char classid[CLASS_ID_MAX_LEN]; char clientid[CLIENT_ID_MAX_LEN]; memset (first_route, 0, sizeof (route_t)); /* The message back never has the class or client id's so we save them */ strcpy (classid, dhcp->classid); strcpy (clientid, dhcp->clientid); free_dhcp (dhcp); memset (dhcp, 0, sizeof (dhcp_t)); dhcp->address.s_addr = message->yiaddr; strcpy (dhcp->servername, message->servername); while (p < end) { option = *p++; if (!option) continue; length = *p++; if (p + length >= end) { retval = -1; goto eexit; } switch (option) { case DHCP_END: goto eexit; case DHCP_MESSAGETYPE: retval = (int) *p; break; #define GET_UINT32(_val) \ memcpy (&_val, p, sizeof (uint32_t)); #define GET_UINT32_H(_val) \ GET_UINT32 (_val); \ _val = ntohl (_val); case DHCP_ADDRESS: GET_UINT32 (dhcp->address.s_addr); break; case DHCP_NETMASK: GET_UINT32 (dhcp->netmask.s_addr); break; case DHCP_BROADCAST: GET_UINT32 (dhcp->broadcast.s_addr); break; case DHCP_SERVERIDENTIFIER: GET_UINT32 (dhcp->serveraddress.s_addr); break; case DHCP_LEASETIME: GET_UINT32_H (dhcp->leasetime); break; case DHCP_RENEWALTIME: GET_UINT32_H (dhcp->renewaltime); break; case DHCP_REBINDTIME: GET_UINT32_H (dhcp->rebindtime); break; case DHCP_MTU: GET_UINT32_H (dhcp->mtu); /* Minimum legal mtu is 68 */ if (dhcp->mtu > 0 && dhcp->mtu < 68) dhcp->mtu = 68; break; #undef GET_UINT32_H #undef GET_UINT32 #define GETSTR(_var) \ if (_var) free (_var); \ _var = xmalloc (length + 1); \ memcpy (_var, p, length); \ memset (_var + length, 0, 1); case DHCP_HOSTNAME: GETSTR (dhcp->hostname); break; case DHCP_DNSDOMAIN: GETSTR (dhcp->dnsdomain); break; case DHCP_MESSAGE: GETSTR (dhcp->message); break; case DHCP_ROOTPATH: GETSTR (dhcp->rootpath); break; case DHCP_NISDOMAIN: GETSTR (dhcp->nisdomain); break; #undef GETSTR #define GETADDR(_var) \ if (_var) free (_var); \ _var = xmalloc (sizeof (address_t)); \ dhcp_add_address (_var, p, length); case DHCP_DNSSERVER: GETADDR (dhcp->dnsservers); break; case DHCP_NTPSERVER: GETADDR (dhcp->ntpservers); break; case DHCP_NISSERVER: GETADDR (dhcp->nisservers); break; #undef GETADDR case DHCP_DNSSEARCH: if (dhcp->dnssearch) free (dhcp->dnssearch); if ((len = decode_search (p, length, NULL))) { dhcp->dnssearch = xmalloc (len); decode_search (p, length, dhcp->dnssearch); } break; case DHCP_CSR: csr = decodeCSR (p, length); break; case DHCP_STATICROUTE: for (i = 0; i < length; i += 8) { memcpy (&route->destination.s_addr, p + i, 4); memcpy (&route->gateway.s_addr, p + i + 4, 4); route->netmask.s_addr = getnetmask (route->destination.s_addr); last_route = route; route->next = xmalloc (sizeof (route_t)); route = route->next; memset (route, 0, sizeof (route_t)); } break; case DHCP_ROUTERS: for (i = 0; i < length; i += 4) { memcpy (&route->gateway.s_addr, p + i, 4); last_route = route; route->next = xmalloc (sizeof (route_t)); route = route->next; memset (route, 0, sizeof (route_t)); } break; default: logger (LOG_DEBUG, "no facility to parse DHCP code %u", option); break; } p += length; } eexit: /* Fill in any missing fields */ if (! dhcp->netmask.s_addr) dhcp->netmask.s_addr = getnetmask (dhcp->address.s_addr); if (! dhcp->broadcast.s_addr) dhcp->broadcast.s_addr = dhcp->address.s_addr | ~dhcp->netmask.s_addr; /* If we have classess static routes then we discard static routes and routers according to RFC 3442 */ if (csr) { dhcp->routes = csr; free_route (first_route); } else { dhcp->routes = first_route; if (last_route) { free (last_route->next); last_route->next = NULL; } else { free_route (dhcp->routes); dhcp->routes = NULL; } } /* The message back never has the class or client id's so we restore them */ strcpy (dhcp->classid, classid); strcpy (dhcp->clientid, clientid); return retval; }
int configure (const options_t *options, interface_t *iface, const dhcp_t *dhcp) { route_t *route = NULL; route_t *new_route = NULL; route_t *old_route = NULL; struct hostent *he = NULL; char newhostname[HOSTNAME_MAX_LEN] = {0}; char curhostname[HOSTNAME_MAX_LEN] = {0}; char *dname = NULL; int dnamel = 0; if (! options || ! iface || ! dhcp) return -1; /* Remove old routes Always do this as the interface may have >1 address not added by us so the routes we added may still exist */ if (iface->previous_routes) { for (route = iface->previous_routes; route; route = route->next) if (route->destination.s_addr || options->dogateway) { int have = 0; if (dhcp->address.s_addr != 0) for (new_route = dhcp->routes; new_route; new_route = new_route->next) if (new_route->destination.s_addr == route->destination.s_addr && new_route->netmask.s_addr == route->netmask.s_addr && new_route->gateway.s_addr == route->gateway.s_addr) { have = 1; break; } if (! have) del_route (iface->name, route->destination, route->netmask, route->gateway, options->metric); } } /* If we don't have an address, then return */ if (dhcp->address.s_addr == 0) { if (iface->previous_routes) { free_route (iface->previous_routes); iface->previous_routes = NULL; } /* Only reset things if we had set them before */ if (iface->previous_address.s_addr != 0) { del_address (iface->name, iface->previous_address, iface->previous_netmask); memset (&iface->previous_address, 0, sizeof (struct in_addr)); memset (&iface->previous_netmask, 0, sizeof (struct in_addr)); restore_resolv (iface->name); /* we currently don't have a resolvconf style programs for ntp/nis */ exec_script (options->script, iface->infofile, "down"); } return 0; } if (add_address (iface->name, dhcp->address, dhcp->netmask, dhcp->broadcast) < 0 && errno != EEXIST) return -1; /* Now delete the old address if different */ if (iface->previous_address.s_addr != dhcp->address.s_addr && iface->previous_address.s_addr != 0) del_address (iface->name, iface->previous_address, iface->previous_netmask); #ifdef __linux__ /* On linux, we need to change the subnet route to have our metric. */ if (iface->previous_address.s_addr != dhcp->address.s_addr && options->metric > 0 && dhcp->netmask.s_addr != INADDR_BROADCAST) { struct in_addr td; struct in_addr tg; memset (&td, 0, sizeof (td)); memset (&tg, 0, sizeof (tg)); td.s_addr = dhcp->address.s_addr & dhcp->netmask.s_addr; add_route (iface->name, td, dhcp->netmask, tg, options->metric); del_route (iface->name, td, dhcp->netmask, tg, 0); } #endif /* Remember added routes */ if (dhcp->routes) { route_t *new_routes = NULL; int remember; for (route = dhcp->routes; route; route = route->next) { /* Don't set default routes if not asked to */ if (route->destination.s_addr == 0 && route->netmask.s_addr == 0 && ! options->dogateway) continue; remember = add_route (iface->name, route->destination, route->netmask, route->gateway, options->metric); /* If we failed to add the route, we may have already added it ourselves. If so, remember it again. */ if (remember < 0) for (old_route = iface->previous_routes; old_route; old_route = old_route->next) if (old_route->destination.s_addr == route->destination.s_addr && old_route->netmask.s_addr == route->netmask.s_addr && old_route->gateway.s_addr == route->gateway.s_addr) { remember = 1; break; } if (remember >= 0) { if (! new_routes) { new_routes = xmalloc (sizeof (route_t)); memset (new_routes, 0, sizeof (route_t)); new_route = new_routes; } else { new_route->next = xmalloc (sizeof (route_t)); new_route = new_route->next; } memcpy (new_route, route, sizeof (route_t)); new_route -> next = NULL; } } if (iface->previous_routes) free_route (iface->previous_routes); iface->previous_routes = new_routes; } if (options->dodns && dhcp->dnsservers) make_resolv(iface->name, dhcp); else logger (LOG_DEBUG, "no dns information to write"); if (options->dontp && dhcp->ntpservers) make_ntp(iface->name, dhcp); if (options->donis && (dhcp->nisservers || dhcp->nisdomain)) make_nis(iface->name, dhcp); /* Now we have made a resolv.conf we can obtain a hostname if we need one */ if (options->dohostname && ! dhcp->hostname) { he = gethostbyaddr (inet_ntoa (dhcp->address), sizeof (struct in_addr), AF_INET); if (he) { dname = he->h_name; while (*dname > 32) dname++; dnamel = dname - he->h_name; memcpy (newhostname, he->h_name, dnamel); newhostname[dnamel] = 0; } } gethostname (curhostname, sizeof (curhostname)); if (options->dohostname || strlen (curhostname) == 0 || strcmp (curhostname, "(none)") == 0 || strcmp (curhostname, "localhost") == 0) { if (dhcp->hostname) strcpy (newhostname, dhcp->hostname); if (*newhostname) { logger (LOG_INFO, "setting hostname to `%s'", newhostname); sethostname (newhostname, strlen (newhostname)); } } write_info (iface, dhcp, options); if (iface->previous_address.s_addr != dhcp->address.s_addr || iface->previous_netmask.s_addr != dhcp->netmask.s_addr) { memcpy (&iface->previous_address, &dhcp->address, sizeof (struct in_addr)); memcpy (&iface->previous_netmask, &dhcp->netmask, sizeof (struct in_addr)); exec_script (options->script, iface->infofile, "new"); } else exec_script (options->script, iface->infofile, "up"); return 0; }