--- dhcp-0.10/libdhcp6client/lease_token.l.libdhcp6client 2004-02-04 18:29:24.000000000 -0500 +++ dhcp-0.10/libdhcp6client/lease_token.l 2006-07-19 01:30:57.000000000 -0400 @@ -241,6 +241,9 @@ fseek(file, 0, 0); yyin = file; + yy_init=1; + yy_start=0; + yy_current_buffer=0; yylex(); return; } --- dhcp-0.10/libdhcp6client/client6_addr.c.libdhcp6client 2006-07-19 01:30:48.000000000 -0400 +++ dhcp-0.10/libdhcp6client/client6_addr.c 2006-07-19 01:30:57.000000000 -0400 @@ -56,6 +56,10 @@ #include "timer.h" #include "lease.h" +#ifdef LIBDHCP +#include "libdhcp_control.h" +#endif + static int dhcp6_update_lease __P((struct dhcp6_addr *, struct dhcp6_lease *)); static int dhcp6_add_lease __P((struct dhcp6_addr *)); struct dhcp6_lease *dhcp6_find_lease __P((struct dhcp6_iaidaddr *, @@ -220,7 +224,7 @@ sp->iaidaddr = &client6_iaidaddr; time(&sp->start_date); sp->state = ACTIVE; - if (write_lease(sp, client6_lease_file) != 0) { + if (client6_lease_file && (write_6_lease(sp, client6_lease_file) != 0)) { dprintf(LOG_ERR, "%s" "failed to write a new lease address %s to lease file", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); if (sp->timer) @@ -231,14 +235,24 @@ if (sp->lease_addr.type == IAPD) { dprintf(LOG_INFO, "request prefix is %s/%d", in6addr2str(&sp->lease_addr.addr, 0), sp->lease_addr.plen); - } else if (client6_ifaddrconf(IFADDRCONF_ADD, addr) != 0) { - dprintf(LOG_ERR, "%s" "adding address failed: %s", - FNAME, in6addr2str(&addr->addr, 0)); - if (sp->timer) + } else +#ifdef LIBDHCP + if ( libdhcp_control + &&(libdhcp_control->capability & DHCP_CONFIGURE_ADDRESSES) + ) + { +#endif + if (client6_ifaddrconf(IFADDRCONF_ADD, addr) != 0) { + dprintf(LOG_ERR, "%s" "adding address failed: %s", + FNAME, in6addr2str(&addr->addr, 0)); + if (sp->timer) dhcp6_remove_timer(sp->timer); - free(sp); - return (-1); - } + free(sp); + return (-1); + } +#ifdef LIBDHCP + } +#endif TAILQ_INSERT_TAIL(&client6_iaidaddr.lease_list, sp, link); /* for infinite lifetime don't do any timer */ if (sp->lease_addr.validlifetime == DHCP6_DURATITION_INFINITE || @@ -285,7 +299,12 @@ dprintf(LOG_DEBUG, "%s" "removing address %s", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); sp->state = INVALID; - if (write_lease(sp, client6_lease_file) != 0) { +#ifdef LIBDHCP + if ( libdhcp_control + &&(libdhcp_control->capability & DHCP_USE_LEASE_DATABASE) + ) +#endif + if (write_6_lease(sp, client6_lease_file) != 0) { dprintf(LOG_INFO, "%s" "failed to write removed lease address %s to lease file", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); @@ -297,10 +316,17 @@ in6addr2str(&sp->lease_addr.addr, 0), sp->lease_addr.plen); /* XXX: remove from the update prefix list */ - } else if (client6_ifaddrconf(IFADDRCONF_REMOVE, &sp->lease_addr) != 0) { + } else +#ifdef LIBDHCP + if ( libdhcp_control + &&(libdhcp_control->capability & DHCP_CONFIGURE_ADDRESSES) + ) +#endif + + if (client6_ifaddrconf(IFADDRCONF_REMOVE, &sp->lease_addr) != 0) { dprintf(LOG_INFO, "%s" "removing address %s failed", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); - } + } /* remove expired timer for this lease. */ if (sp->timer) dhcp6_remove_timer(sp->timer); @@ -453,7 +479,12 @@ memcpy(&sp->lease_addr, addr, sizeof(sp->lease_addr)); sp->state = ACTIVE; time(&sp->start_date); - if (write_lease(sp, client6_lease_file) != 0) { +#ifdef LIBDHCP + if ( libdhcp_control + &&(libdhcp_control->capability & DHCP_USE_LEASE_DATABASE) + ) +#endif + if (write_6_lease(sp, client6_lease_file) != 0) { dprintf(LOG_ERR, "%s" "failed to write an updated lease address %s to lease file", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); @@ -677,7 +708,7 @@ return (-1); } - dprintf(LOG_DEBUG, "%s" "%s an address %s on %s", FNAME, cmdstr, + dprintf(LOG_INFO, "%s" "%s an address %s on %s", FNAME, cmdstr, in6addr2str(&ifaddr->addr, 0), ifp->ifname); close(s); return (0); @@ -707,7 +738,7 @@ create_iaid(struct iaid_table *iaidtab, int num_device) { struct iaid_table *temp = iaidtab; - struct ifaddrs *ifa=0L, *ifap=0L; + struct ifaddrs *ifap=0L,*ifa=0L; int i; if ( getifaddrs( &ifap ) != 0 ) @@ -716,7 +747,7 @@ return -1; } - for (i=0, ifa = ifap; + for (i=0, ifa=ifap; (ifa != 0L) && ( i < MAX_DEVICE ); i++, ifa = ifa->ifa_next ) --- dhcp-0.10/libdhcp6client/dhcp6c.c.libdhcp6client 2006-07-19 01:30:48.000000000 -0400 +++ dhcp-0.10/libdhcp6client/dhcp6c.c 2006-07-19 01:30:57.000000000 -0400 @@ -73,6 +73,9 @@ #include "common.h" #include "timer.h" #include "lease.h" +#ifdef LIBDHCP +#include "libdhcp_control.h" +#endif static int debug = 0; static u_long sig_flags = 0; @@ -103,9 +106,9 @@ #define CLIENT6_INFO_REQ 0x10 -int insock; /* inbound udp port */ -int outsock; /* outbound udp port */ -int nlsock; +int insock = -1; /* inbound udp port */ +int outsock= -1; /* outbound udp port */ +int nlsock = -1; extern char *raproc_file; extern char *ifproc_file; @@ -155,20 +158,35 @@ #define DUID_FILE "/var/lib/dhcpv6/dhcp6c_duid" static int pid; +#ifdef LIBDHCP +struct sockaddr_in6 sa6_allagent_storage; +#endif //static char cmdbuf[1024]; //static char oldlink[256]; char client6_lease_temp[256]; struct dhcp6_list request_list; -int -main(argc, argv) +#ifndef LIBDHCP +int main +(argc, argv, envp) +#else +#define exit return +LIBDHCP_Control *libdhcp_control; +int dhcpv6_client +(libdhcp_ctl, argc, argv, envp) + LIBDHCP_Control *libdhcp_ctl; +#endif int argc; char **argv; + char **envp; { int ch; char *progname, *conffile = DHCP6C_CONF; FILE *pidfp; char *addr; +#ifdef LIBDHCP + libdhcp_control = libdhcp_ctl; +#endif pid = getpid(); srandom(time(NULL) & pid); @@ -284,16 +302,22 @@ err(1, "daemon"); openlog(progname, LOG_NDELAY|LOG_PID, LOG_DAEMON); } + setloglevel(debug); +#ifndef LIBDHCP + if ( libdhcp_control && ( libdhcp_control->capability & DHCP_USE_PID_FILE ) ) +#endif /* dump current PID */ if ((pidfp = fopen(DHCP6C_PIDFILE, "w")) != NULL) { fprintf(pidfp, "%d\n", pid); fclose(pidfp); } - +#ifdef LIBDHCP + sa6_allagent = (const struct sockaddr_in6 *)&sa6_allagent_storage; +#endif ifinit(device); - + setup_interface(device); if ((cfparse(conffile)) != 0) { dprintf(LOG_ERR, "%s" "failed to parse configuration file", FNAME); @@ -302,7 +326,55 @@ client6_init(device); client6_ifinit(device); client6_mainloop(); - exit(0); +#ifdef LIBDHCP + /* close all file descriptors */ + close(nlsock); + nlsock = -1; + close(insock); + insock = -1; + close(outsock); + outsock = -1; + closelog(); + /* release all memory */ + sleep(1); /* keep valgrind happy :-) */ + dhc6_free_all_pointers(); + /* initialize globals */ + optarg = 0L; + optind = 0; + opterr = 0; + optopt = 0; + memset( &client6_iaidaddr, '\0', sizeof(client6_iaidaddr)); + dhcp6_if = 0L; + dadlist = 0L; + extern LIST_HEAD(, dhcp6_timer) timer_head; + memset( &timer_head, '\0', sizeof(timer_head)); + memset( &request_list, '\0', sizeof(request_list)); + memset( &sa6_allagent_storage, '\0', sizeof(sa6_allagent_storage)); + sa6_allagent = (const struct sockaddr_in6 *)&sa6_allagent_storage; + memset( &client_duid, '\0', sizeof(client_duid)); + memset( &iaidtab, '\0', sizeof(iaidtab)); + client6_request_flag =0; + memset( &leasename, '\0', sizeof(leasename)); + debug = 0; + device = 0L; + num_device=0; + sig_flags = 0; + extern struct host_conf *host_conflist; + host_conflist = 0; + client6_lease_file = server6_lease_file = sync_file = 0L; + cf_dns_list = 0L; + extern int cfdebug; + cfdebug = 0; + hash_anchors = 0; + configfilename = 0L; + debug_thresh = 0; + memset( &dnslist, '\0', sizeof(dnslist)); + memset( &radvd_dhcpv6_file, '\0', sizeof(radvd_dhcpv6_file)); + memset( &resolv_dhcpv6_file, '\0', sizeof(resolv_dhcpv6_file)); + memset( &client6_lease_temp, '\0', sizeof(client6_lease_temp)); + foreground = 0; +#endif + return(0); } static void @@ -321,13 +393,17 @@ char *device; { struct addrinfo hints, *res; +#ifndef LIBDHCP static struct sockaddr_in6 sa6_allagent_storage; +#endif int error, on = 1; struct dhcp6_if *ifp; int ifidx; // struct ifaddrs *ifa, *ifap; char linklocal[64]; struct in6_addr lladdr; + time_t retry, now; + int bound; ifidx = if_nametoindex(device); if (ifidx == 0) { @@ -346,7 +422,7 @@ if (inet_ntop(AF_INET6, &lladdr, linklocal, sizeof(linklocal)) < 0) { exit(1); } - dprintf(LOG_DEBUG, "link local addr is %s", linklocal); + dprintf(LOG_INFO, "link local addr is %s", linklocal); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET6; @@ -382,12 +458,40 @@ } #endif ((struct sockaddr_in6 *)(res->ai_addr))->sin6_scope_id = ifidx; - dprintf(LOG_DEBUG, "res addr is %s/%d", addr2str(res->ai_addr, res->ai_addrlen), res->ai_addrlen); - if (bind(insock, res->ai_addr, res->ai_addrlen) < 0) { - dprintf(LOG_ERR, "%s" "bind(inbound): %s", - FNAME, strerror(errno)); - exit(1); - } + dprintf(LOG_INFO, "inbound addr is %s/%d", addr2str(res->ai_addr, res->ai_addrlen ), res->ai_addrlen); + + /* + * If the interface has JUST been brought up, the kernel may not + * have enough time to allow the bind to the linklocal address - + * it will then return EADDRNOTAVAIL. The bind will succeed if + * we try again: + */ + retry = now = time(0); + bound = 0; + do + { + if (bind(insock, res->ai_addr, res->ai_addrlen) < 0) + { + bound = -errno; + retry = time(0); + if( ( bound != -EADDRNOTAVAIL ) || ( (retry - now) > 5 )) + break; + struct timespec tv = { 0, 200000000 }; + nanosleep(&tv,0); + }else + { + bound = 1; + break; + } + } while( (retry - now) < 5 ); + + if( bound < 0 ) + { + dprintf(LOG_ERR, "%s" "bind(inbound): %s", + FNAME, strerror(-bound)); + exit(bound); + } + freeaddrinfo(res); hints.ai_flags = 0; @@ -411,18 +515,13 @@ exit(1); } ((struct sockaddr_in6 *)(res->ai_addr))->sin6_scope_id = ifidx; + dprintf(LOG_INFO, "outbound addr is %s/%d", addr2str(res->ai_addr, res->ai_addrlen), res->ai_addrlen); if (bind(outsock, res->ai_addr, res->ai_addrlen) < 0) { dprintf(LOG_ERR, "%s" "bind(outbound): %s", FNAME, strerror(errno)); exit(1); } freeaddrinfo(res); - /* open a socket to watch the off-on link for confirm messages */ - if ((nlsock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - dprintf(LOG_ERR, "%s" "open a socket: %s", - FNAME, strerror(errno)); - exit(1); - } memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_DGRAM; @@ -445,7 +544,7 @@ exit(1); } ifp->outsock = outsock; - +#ifndef LIBDHCP if (signal(SIGHUP, client6_signal) == SIG_ERR) { dprintf(LOG_WARNING, "%s" "failed to set signal: %s", FNAME, strerror(errno)); @@ -461,6 +560,7 @@ FNAME, strerror(errno)); exit(1); } +#endif } static void @@ -489,6 +589,10 @@ memcpy(&client6_iaidaddr.client6_info.iaidinfo, &ifp->iaidinfo, sizeof(client6_iaidaddr.client6_info.iaidinfo)); duidcpy(&client6_iaidaddr.client6_info.clientid, &client_duid); +#ifdef LIBDHCP + if ( libdhcp_control && ( libdhcp_control->capability & DHCP_USE_LEASE_DATABASE ) ) + { +#endif /* parse the lease file */ strcpy(leasename, PATH_CLIENT6_LEASE); sprintf(iaidstr, "%u", ifp->iaidinfo.iaid); @@ -504,6 +608,9 @@ sync_leases(client6_lease_file, leasename, client6_lease_temp); if (client6_lease_file == NULL) exit(1); +#ifdef LIBDHCP + } +#endif if (!TAILQ_EMPTY(&client6_iaidaddr.lease_list)) { // struct dhcp6_lease *cl; struct dhcp6_listval *lv; @@ -529,7 +636,7 @@ dprintf(LOG_INFO, "no ipv6 addresses are leased by client"); exit(0); } - setup_interface(ifp->ifname); +/* setup_interface(ifp->ifname); */ ifp->link_flag |= IFF_RUNNING; /* get addrconf prefix from kernel */ @@ -576,6 +683,11 @@ else { for (sp = TAILQ_FIRST(&client6_iaidaddr.lease_list); sp; sp = sp_next) { sp_next = TAILQ_NEXT(sp, link); +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_ADDRESSES ) + ) +#endif if (client6_ifaddrconf(IFADDRCONF_REMOVE, &sp->lease_addr) != 0) dprintf(LOG_INFO, "%s" "deconfiging address %s failed", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); @@ -587,6 +699,11 @@ ev_next = TAILQ_NEXT(ev, link); dhcp6_remove_event(ev); } +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_RADVD ) + ) +#endif /* XXX: check the last dhcpv6 client daemon to restore the original file */ { /* restore /etc/radv.conf.bak back to /etc/radvd.conf */ @@ -626,19 +743,72 @@ static void client6_mainloop() { - struct timeval *w; + struct timeval *w; int ret; fd_set r; +#ifdef LIBDHCP + struct timeval fb /* fallback timeout */; + + if ( libdhcp_control ) + { + if ( libdhcp_control->timeout ) + libdhcp_control->now = time(0); + else + libdhcp_control->now = 0; + } +#endif + while(1) { if (sig_flags) process_signals(); - w = dhcp6_check_timer(); + w = dhcp6_check_timer(); +#ifdef LIBDHCP + if ( libdhcp_control && libdhcp_control->timeout ) + { + time_t now = time(0); + if ( (w == 0L) + ||( ( ((double)(w->tv_sec + now )) + +(((double)(w->tv_usec))/1000000.0) + ) >= + ( ((double)libdhcp_control->now) + +((double)libdhcp_control->timeout) + ) + ) + ) + { + w = &fb; + fb.tv_sec = 0; + fb.tv_usec = 0; + if ( now < ( libdhcp_control->now + libdhcp_control->timeout ) ) + fb.tv_sec = (libdhcp_control->now + libdhcp_control->timeout) - now; + } + + } +#endif FD_ZERO(&r); FD_SET(insock, &r); + dprintf(LOG_DEBUG,"\n\nentering select - client state: %d %s timeout: %p %lu %lu\n", + client6_iaidaddr.state, + (client6_iaidaddr.state == DHCP6_ACTIVE) + ? "ACTIVE" + :(client6_iaidaddr.state == DHCP6_RENEW) + ? "RENEW" + :(client6_iaidaddr.state == DHCP6_REBIND) + ? "REBIND" + :(client6_iaidaddr.state == DHCP6_EXPIRED) + ? "EXPIRED" + :(client6_iaidaddr.state == DHCP6_INVALID) + ?"INVALID" + :"UNKNOWN", w, + w ? w -> tv_sec : 0, + w ? w -> tv_usec: 0 + ); + ret = select(insock + 1, &r, NULL, NULL, w); + switch (ret) { case -1: if (errno != EINTR) { @@ -650,8 +820,36 @@ case 0: /* timeout */ break; /* dhcp6_check_timer() will treat the case */ default: /* received a packet */ + dprintf(LOG_DEBUG,"client_recv"); client6_recv(); + } +#ifdef LIBDHCP + if ( libdhcp_control ) + { + dprintf(LOG_INFO,"libdhcp_check"); + if( libdhcp_control->finished ) + return; + + if( libdhcp_control->timeout + &&( time(0L) >= + ( libdhcp_control->timeout + + libdhcp_control->now + ) + ) + ) + { + if ( libdhcp_control -> callback ) + (*( libdhcp_control -> callback ) ) + ( + libdhcp_control, + DHC_TIMEDOUT, + &client6_iaidaddr + ); + return; + } + } +#endif } } @@ -678,6 +876,7 @@ switch(ev->state) { case DHCP6S_INIT: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_INIT"); /* From INIT state client could * go to CONFIRM state if the client reboots; * go to RELEASE state if the client issues a release; @@ -717,6 +916,7 @@ ev->state = DHCP6S_SOLICIT; dhcp6_set_timeoparam(ev); case DHCP6S_SOLICIT: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_SOLICIT"); if (ifp->servers) { ifp->current_server = select_server(ifp); if (ifp->current_server == NULL) { @@ -727,7 +927,7 @@ } /* if get the address assginment break */ if (!TAILQ_EMPTY(&client6_iaidaddr.lease_list)) { - dhcp6_remove_event(ev); + dhcp6_remove_event(ev); return (NULL); } ev->timeouts = 0; @@ -735,14 +935,21 @@ dhcp6_set_timeoparam(ev); } case DHCP6S_INFOREQ: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_INFOREQ"); case DHCP6S_REQUEST: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_REQUEST"); client6_send(ev); break; case DHCP6S_RELEASE: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_RELEASE"); case DHCP6S_DECLINE: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_DECLINE"); case DHCP6S_CONFIRM: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_CONFIRM"); case DHCP6S_RENEW: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_RENEW"); case DHCP6S_REBIND: + dprintf(LOG_DEBUG,"client6_timo - DHCP6_REBIND"); if (!TAILQ_EMPTY(&request_list)) client6_send(ev); else { @@ -825,9 +1032,11 @@ switch(ev->state) { case DHCP6S_SOLICIT: + dprintf(LOG_DEBUG,"send state SOLICIT"); dh6->dh6_msgtype = DH6_SOLICIT; break; case DHCP6S_REQUEST: + dprintf(LOG_DEBUG,"send state REQUEST"); if (ifp->current_server == NULL) { dprintf(LOG_ERR, "%s" "assumption failure", FNAME); exit(1); /* XXX */ @@ -835,6 +1044,7 @@ dh6->dh6_msgtype = DH6_REQUEST; break; case DHCP6S_RENEW: + dprintf(LOG_DEBUG,"send state RENEW"); if (ifp->current_server == NULL) { dprintf(LOG_ERR, "%s" "assumption failure", FNAME); exit(1); /* XXX */ @@ -842,6 +1052,7 @@ dh6->dh6_msgtype = DH6_RENEW; break; case DHCP6S_DECLINE: + dprintf(LOG_DEBUG,"send state DECLINE"); if (ifp->current_server == NULL) { dprintf(LOG_ERR, "%s" "assumption failure", FNAME); exit(1); /* XXX */ @@ -849,15 +1060,19 @@ dh6->dh6_msgtype = DH6_DECLINE; break; case DHCP6S_INFOREQ: + dprintf(LOG_DEBUG,"send state INFOREQ"); dh6->dh6_msgtype = DH6_INFORM_REQ; break; case DHCP6S_REBIND: + dprintf(LOG_DEBUG,"send state REBIND"); dh6->dh6_msgtype = DH6_REBIND; break; case DHCP6S_CONFIRM: + dprintf(LOG_DEBUG,"send state CONFIRM"); dh6->dh6_msgtype = DH6_CONFIRM; break; case DHCP6S_RELEASE: + dprintf(LOG_DEBUG,"send state RELEASE"); dh6->dh6_msgtype = DH6_RELEASE; break; default: @@ -999,12 +1214,34 @@ /* XXX: allow the other emtpy list ?? */ } if (client6_request_flag & CLIENT6_RELEASE_ADDR) { +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_ADDRESSES ) + ) + +#endif if (dhcp6_update_iaidaddr(&optinfo, ADDR_REMOVE)) { dprintf(LOG_INFO, "client release failed"); exit(1); } +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_RADVD ) + ) + +#endif if (client6_iaidaddr.client6_info.type == IAPD) radvd_parse(&client6_iaidaddr, ADDR_REMOVE); + +#ifdef LIBDHCP + if( libdhcp_control && libdhcp_control->callback ) + (*(libdhcp_control->callback)) + ( libdhcp_control, + DHC6_RELEASE, + &client6_iaidaddr + ); +#endif + } break; default: @@ -1087,6 +1324,7 @@ struct cmsghdr *cm; struct in6_pktinfo *pi = NULL; + dprintf(LOG_DEBUG,"\nclient6_recv\n"); memset(&iov, 0, sizeof(iov)); memset(&mhdr, 0, sizeof(mhdr)); @@ -1144,9 +1382,11 @@ switch(dh6->dh6_msgtype) { case DH6_ADVERTISE: + dprintf(LOG_DEBUG,"client6_recv RECVADVERT"); (void)client6_recvadvert(ifp, dh6, len, &optinfo); break; case DH6_REPLY: + dprintf(LOG_DEBUG,"client6_recv RECVREPLY"); (void)client6_recvreply(ifp, dh6, len, &optinfo); break; default: @@ -1155,7 +1395,6 @@ addr2str((struct sockaddr *)&from, sizeof(((struct sockaddr *)&from)->sa_data))); break; } - dhcp6_clear_options(&optinfo); return; } @@ -1266,7 +1505,22 @@ /* if the client send preferred addresses reqeust in SOLICIT */ /* XXX: client might have some local policy to select the addresses */ if (!TAILQ_EMPTY(&optinfo0->addr_list)) + { +#ifdef LIBDHCP + if ( ! TAILQ_EMPTY( &(client6_iaidaddr.lease_list) ) ) + /* looks like we did a successful REBIND ? */ + if( libdhcp_control && libdhcp_control->callback ) + { + (*(libdhcp_control->callback)) + ( + libdhcp_control, + DHC6_REBIND, + optinfo0 + ); + } +#endif dhcp6_copy_list(&request_list, &optinfo0->addr_list); + } return 0; } @@ -1354,6 +1608,7 @@ int addr_status_code = DH6OPT_STCODE_UNSPECFAIL; struct dhcp6_serverinfo *newserver; int newstate = 0; + dprintf(LOG_DEBUG, "RECV REPLY"); /* find the corresponding event based on the received xid */ dprintf(LOG_DEBUG, "%s" "reply message XID is (%x)", FNAME, ntohl(dh6->dh6_xid) & DH6_XIDMASK); @@ -1377,13 +1632,16 @@ dprintf(LOG_INFO, "%s" "no server ID option", FNAME); return -1; } - dprintf(LOG_DEBUG, "%s" "serverID is %s len is %d", FNAME, + dprintf(LOG_INFO, "%s" "serverID is %s len is %d", FNAME, duidstr(&optinfo->serverID), optinfo->serverID.duid_len); /* get current server */ switch (ev->state) { case DHCP6S_SOLICIT: + dprintf(LOG_DEBUG, "%s" "state SOLICIT",FNAME); case DHCP6S_CONFIRM: + dprintf(LOG_DEBUG, "%s" "state CONFIRM",FNAME); case DHCP6S_REBIND: + dprintf(LOG_DEBUG, "%s" "state REBIND",FNAME); newserver = allocate_newserver(ifp, optinfo); if (newserver == NULL) return (-1); @@ -1406,11 +1664,13 @@ dprintf(LOG_INFO, "%s" "client DUID mismatch", FNAME); return -1; } + if (!TAILQ_EMPTY(&optinfo->dns_list.addrlist) || + optinfo->dns_list.domainlist != NULL) - if (!TAILQ_EMPTY(&optinfo->dns_list.addrlist) || - optinfo->dns_list.domainlist != NULL) { - resolv_parse(&optinfo->dns_list); - } +#ifdef LIBDHCP + if ( libdhcp_control && (libdhcp_control->capability & DHCP_CONFIGURE_RESOLVER) ) +#endif + resolv_parse(&optinfo->dns_list); /* * The client MAY choose to report any status code or message from the * status code option in the Reply message. @@ -1437,7 +1697,7 @@ switch (addr_status_code) { case DH6OPT_STCODE_UNSPECFAIL: case DH6OPT_STCODE_USEMULTICAST: - dprintf(LOG_INFO, "%s" "status code: %s", FNAME, + dprintf(LOG_INFO, "%s" "status code: %s - RETRANSMIT", FNAME, dhcp6_stcodestr(addr_status_code)); /* retransmit the message with multicast address */ /* how many time allow the retransmission with error status code? */ @@ -1452,6 +1712,7 @@ */ switch (ev->state) { case DHCP6S_SOLICIT: + dprintf(LOG_DEBUG, "%s" "state SOLICIT",FNAME); if (optinfo->iaidinfo.iaid == 0) break; else if (!optinfo->flags & DHCIFF_RAPID_COMMIT) { @@ -1459,6 +1720,7 @@ break; } case DHCP6S_REQUEST: + dprintf(LOG_DEBUG, "%s" "state REQUEST",FNAME); /* NotOnLink: 1. SOLICIT * NoAddrAvail: Information Request */ switch(addr_status_code) { @@ -1479,32 +1741,57 @@ case DH6OPT_STCODE_SUCCESS: case DH6OPT_STCODE_UNDEFINE: default: + dprintf(LOG_DEBUG, "%s" "addr_status_code SUCCESS/UNDEFINE",FNAME); if (!TAILQ_EMPTY(&optinfo->addr_list)) { (void)get_if_rainfo(ifp); dhcp6_add_iaidaddr(optinfo); if (optinfo->type == IAPD) + { +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_RADVD ) + ) +#endif radvd_parse(&client6_iaidaddr, ADDR_UPDATE); - else if (ifp->dad_timer == NULL && (ifp->dad_timer = + }else if (ifp->dad_timer == NULL && (ifp->dad_timer = dhcp6_add_timer(check_dad_timo, ifp)) < 0) { dprintf(LOG_INFO, "%s" "failed to create a timer for " " DAD", FNAME); - } + } setup_check_timer(ifp); +#ifdef LIBDHCP + if( libdhcp_control && libdhcp_control->callback ) + (*(libdhcp_control -> callback)) + ( libdhcp_control, + DHC6_BOUND, + optinfo + ); +#endif } break; } break; case DHCP6S_RENEW: + dprintf(LOG_DEBUG, "%s" "state RENEW",FNAME); case DHCP6S_REBIND: + dprintf(LOG_DEBUG, "%s" "state REBIND",FNAME); if (client6_request_flag & CLIENT6_CONFIRM_ADDR) goto rebind_confirm; /* NoBinding for RENEW, REBIND, send REQUEST */ switch(addr_status_code) { - case DH6OPT_STCODE_NOBINDING: + case DH6OPT_STCODE_NOBINDING: newstate = DHCP6S_REQUEST; dprintf(LOG_DEBUG, "%s" "got a NoBinding reply, sending request.", FNAME); dhcp6_remove_iaidaddr(&client6_iaidaddr); +#ifdef LIBDHCP + if( libdhcp_control && libdhcp_control->callback ) + (*(libdhcp_control -> callback)) + ( libdhcp_control, + DHC6_RELEASE, + &client6_iaidaddr + ); +#endif break; case DH6OPT_STCODE_NOADDRAVAIL: case DH6OPT_STCODE_NOPREFIXAVAIL: @@ -1515,11 +1802,26 @@ default: dhcp6_update_iaidaddr(optinfo, ADDR_UPDATE); if (optinfo->type == IAPD) +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_RADVD ) + ) +#endif radvd_parse(&client6_iaidaddr, ADDR_UPDATE); +#ifdef LIBDHCP + if( libdhcp_control && libdhcp_control->callback ) + (*(libdhcp_control -> callback)) + ( libdhcp_control, + DHC6_REBIND, + optinfo + ); +#endif break; + } break; case DHCP6S_CONFIRM: + dprintf(LOG_DEBUG, "%s" "state CONFIRM - goto SOLICIT",FNAME); /* NOtOnLink for a Confirm, send SOLICIT message */ rebind_confirm: client6_request_flag &= ~CLIENT6_CONFIRM_ADDR; switch(addr_status_code) { @@ -1537,6 +1839,7 @@ break; case DH6OPT_STCODE_SUCCESS: case DH6OPT_STCODE_UNDEFINE: + dprintf(LOG_DEBUG, "%s" "CONFIRM: addr_status_code SUCCESS/UNDEFINE",FNAME); /* XXX: set up renew/rebind timer */ dprintf(LOG_DEBUG, "%s" "got an expected reply for confirm", FNAME); ftime(&now); @@ -1559,7 +1862,7 @@ if ( offset > client6_iaidaddr.client6_info.iaidinfo.renewtime) timo.tv_sec = 0; else - timo.tv_sec = client6_iaidaddr.client6_info.iaidinfo.renewtime - offset; + timo.tv_sec = client6_iaidaddr.client6_info.iaidinfo.renewtime - offset; timo.tv_usec = 0; dhcp6_set_timer(&timo, client6_iaidaddr.timer); /* check DAD */ @@ -1575,6 +1878,7 @@ } break; case DHCP6S_DECLINE: + dprintf(LOG_DEBUG, "%s" "state DECLINE",FNAME); /* send REQUEST message to server with none decline address */ dprintf(LOG_DEBUG, "%s" "got an expected reply for decline, sending request.", FNAME); @@ -1583,6 +1887,7 @@ newstate = DHCP6S_REQUEST; break; case DHCP6S_RELEASE: + dprintf(LOG_DEBUG, "%s" "state RELEASE",FNAME); dprintf(LOG_INFO, "%s" "got an expected release, exit.", FNAME); dhcp6_remove_event(ev); exit(0); @@ -1604,6 +1909,8 @@ int state; { struct dhcp6_event *ev; + dprintf(LOG_DEBUG,"send_newstate: %d", state); + if ((ev = dhcp6_create_event(ifp, state)) == NULL) { dprintf(LOG_ERR, "%s" "failed to create an event", FNAME); @@ -1662,6 +1969,11 @@ /* config the interface for reboot */ if (reboot && client6_iaidaddr.client6_info.type != IAPD && (client6_request_flag & CLIENT6_CONFIRM_ADDR)) { +#ifdef LIBDHCP + if ( libdhcp_control + &&(libdhcp_control->capability & DHCP_CONFIGURE_ADDRESSES) + ) +#endif if (client6_ifaddrconf(IFADDRCONF_ADD, &cl->lease_addr) != 0) { dprintf(LOG_INFO, "config address failed: %s", in6addr2str(&cl->lease_addr.addr, 0)); @@ -1672,6 +1984,11 @@ /* update radvd.conf for prefix delegation */ if (reboot && client6_iaidaddr.client6_info.type == IAPD && (client6_request_flag & CLIENT6_CONFIRM_ADDR)) +#ifdef LIBDHCP + if( libdhcp_control + && (libdhcp_control->capability & DHCP_CONFIGURE_RADVD ) + ) +#endif radvd_parse(&client6_iaidaddr, ADDR_UPDATE); return (0); } @@ -1763,8 +2080,9 @@ int newstate; dprintf(LOG_DEBUG, "enter checking link ..."); strncpy(ifr.ifr_name, dhcp6_if->ifname, IFNAMSIZ); + dprintf(LOG_DEBUG,"check_link_timo: ioctl SIOCIGIFFLAGS"); if (ioctl(nlsock, SIOCGIFFLAGS, &ifr) < 0) { - dprintf(LOG_DEBUG, "ioctl SIOCGIFFLAGS failed"); + dprintf(LOG_DEBUG, "check_link_timo: ioctl SIOCGIFFLAGS failed"); goto settimer; } if (ifr.ifr_flags & IFF_RUNNING) { @@ -1806,29 +2124,48 @@ setup_interface(char *ifname) { struct ifreq ifr; + int retries = 0; /* check the interface */ + + dprintf(LOG_INFO,"setup interface"); + + /* open a socket to watch the off-on link for confirm messages */ + if ((nlsock == -1) && ((nlsock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)) { + dprintf(LOG_ERR, "%s" "open a socket: %s", + FNAME, strerror(errno)); + exit(1); + } + memset(&ifr,'\0',sizeof(struct ifreq)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); -again: if (ioctl(nlsock, SIOCGIFFLAGS, &ifr) < 0) { dprintf(LOG_ERR, "ioctl SIOCGIFFLAGS failed"); exit(1); } - if (!ifr.ifr_flags & IFF_UP) { - ifr.ifr_flags |= IFF_UP; - if (ioctl(nlsock, SIOCSIFFLAGS, &ifr) < 0) { - dprintf(LOG_ERR, "ioctl SIOCSIFFLAGS failed"); - exit(1); - } - if (ioctl(nlsock, SIOCGIFFLAGS, &ifr) < 0) { - dprintf(LOG_ERR, "ioctl SIOCGIFFLAGS failed"); - exit(1); - } - } - if (!ifr.ifr_flags & IFF_RUNNING) { - dprintf(LOG_INFO, "NIC is not connected to the network, " - "please connect it. dhcp6c is sleeping ..."); - sleep(10); - goto again; + while( (ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) + { + if( retries++ > 1 ) + { + dprintf(LOG_INFO, "NIC is not connected to the network, " + "please connect it."); + exit(1); + } + memset(&ifr,'\0',sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING) ; + dprintf(LOG_INFO,"ioctl SIOCISIFFLAGS (UP | RUNNING)"); + if (ioctl(nlsock, SIOCSIFFLAGS, &ifr) < 0) { + dprintf(LOG_ERR, "ioctl SIOCSIFFLAGS failed"); + exit(1); + } + sleep(2); /* give kernel time to assign link local address + * and to find / respond to IPv6 routers .. + */ + memset(&ifr,'\0',sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if (ioctl(nlsock, SIOCGIFFLAGS, &ifr) < 0) { + dprintf(LOG_ERR, "ioctl SIOCGIFFLAGS failed"); + exit(1); + } } return; } --- /dev/null 2006-07-18 14:52:55.494029261 -0400 +++ dhcp-0.10/libdhcp6client/libdhcp_control.h 2006-07-19 01:30:57.000000000 -0400 @@ -0,0 +1,104 @@ +/* libdhcp_control.h + * + * DHCP client control API for libdhcp, a minimal interface to the + * ISC dhcp IPv4 client libdhcp4client library, + * and to the dhcpv6 DHCPv6 client libdhcp6client library. + * + * Each DHCP client library must include this file to be controlled + * by libdhcp. + * + * Copyright(C) Jason Vas Dias <jvdias@redhat.com> Red Hat Inc. May 2006 + * + * 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 at + * http://www.fsf.org/licensing/licenses/gpl.txt + * and included in this software distribution as the "LICENSE" file. + * + * 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. + */ +#ifndef LIBDHCP_CONTROL_H +#define LIBDHCP_CONTROL_H + +#include <stdint.h> +#include <stdarg.h> + +#define LOG_FATAL 8 + +enum dhcp_state_e; +struct libdhcp_control_s; + +typedef +int ( *LIBDHCP_Error_Handler ) + ( struct libdhcp_control_s *ctl, + int priority, /* ala syslog(3): LOG_EMERG=0 - LOG_DEBUG=7 (+ LOG_FATAL=8 : finished -> 1) */ + const char *fmt, + va_list ap + ); + +typedef +int ( *LIBDHCP_Callback ) ( struct libdhcp_control_s *control, enum dhcp_state_e, void* ); + /* The DHCP clients will call the users' callback on important state change events, + * with the second arg set to the client DHCP_State, and the third arg set to + * a client specific pointer as described below. + */ + +typedef +struct libdhcp_control_s +{ + LIBDHCP_Callback callback; /* the DHCP clients' main loop calls this on state changes */ + uint16_t capability; /* LIBDHCP_Capability bits to enable */ + uint8_t finished; /* set to one to make clients exit their main loop */ + uint8_t decline; /* set to one to decline the lease (DHCPv4 only) */ + time_t timeout; /* (timeout+now) == time after which clients MUST return */ + time_t now; /* clients set this to time(0) on entering main loop */ + void *arg; /* user data pointer */ + LIBDHCP_Error_Handler eh; +} LIBDHCP_Control; + +typedef enum dhcp_state_e +{ + + /* DHCPv4 client states - third callback arg will be a 'struct client_state *' */ + DHC4_NBI, /* failed: no broadcast interfaces found */ + DHC4_PREINIT, /* configuration started - bring the interface "UP" */ + DHC4_BOUND, /* lease obtained */ + DHC4_RENEW, /* lease renewed */ + DHC4_REBOOT, /* have valid lease, but now obtained a different one */ + DHC4_REBIND, /* new, different lease */ + DHC4_STOP, /* remove old lease */ + DHC4_MEDIUM, /* media selection begun */ + DHC4_TIMEOUT, /* timed out contacting DHCP server */ + DHC4_FAIL, /* all attempts to contact server timed out, sleeping */ + DHC4_EXPIRE, /* lease has expired, renewing */ + DHC4_RELEASE, /* releasing lease */ + /* This state raised by both clients: */ + DHC_TIMEDOUT, /* libdhcp_control timeout has been exceeded */ + /* DHCPv6 client states: */ + DHC6_BOUND, /* new lease obtained - arg is optinfo * */ + DHC6_REBIND, /* existing expired lease rebound - arg is optinfo * */ + DHC6_RELEASE /* existing lease expired - arg is dhcp6_iaidaddr*/ +} DHCP_State; + +typedef enum libdhcp_capability_e +{/* DHCP client "capabilities" */ + DHCP_USE_LEASE_DATABASE = 1, /* use / do not use persistent lease database files */ + DHCP_USE_PID_FILE = 2, /* use / do not use pid file */ + /* + * DHCPv6 supports these capabilities in process, + * while the DHCPv4 client will fork and exec the dhclient-script to implement them if these + * bits are set - otherwise, if no bits are set, the callback is called and the script is + * not run. + */ + DHCP_CONFIGURE_INTERFACES = 4, /* configure interfaces UP/DOWN as required */ + DHCP_CONFIGURE_ADDRESSES = 8, /* configure interface addresses as required */ + DHCP_CONFIGURE_ROUTES =16, /* configure routes as required */ + DHCP_CONFIGURE_RESOLVER =32, /* configure resolv.conf as required */ + /* DHCPv6 only: */ + DHCP_CONFIGURE_RADVD =64, /* configure radvd.conf & restart radvd as required */ +} LIBDHCP_Capability; + +#endif --- /dev/null 2006-07-18 14:52:55.494029261 -0400 +++ dhcp-0.10/libdhcp6client/dhc6_alloc.h 2006-07-19 01:30:57.000000000 -0400 @@ -0,0 +1,17 @@ + +extern void *dhc6_alloc( size_t ); +extern void *dhc6_realloc(void *, size_t); +extern void *dhc6_calloc(size_t, size_t); +extern char *dhc6_strdup(char *str); +extern void dhc6_free( void *); +extern void dhc6_free_all_pointers(void); +#undef malloc +#define malloc( size ) dhc6_alloc( size ) +#undef realloc +#define realloc(ptr, size) dhc6_realloc(ptr, size) +#undef calloc +#define calloc(n, size) dhc6_calloc(n, size) +#undef free +#define free( ptr ) dhc6_free( ptr ) +#undef strdup +#define strdup( str ) dhc6_strdup( str ) --- dhcp-0.10/libdhcp6client/lease.c.libdhcp6client 2004-03-03 15:11:16.000000000 -0500 +++ dhcp-0.10/libdhcp6client/lease.c 2006-07-19 01:30:57.000000000 -0400 @@ -64,7 +64,7 @@ static int init_lease_hashes __P((void)); int -write_lease(const struct dhcp6_lease *lease_ptr, +write_6_lease(const struct dhcp6_lease *lease_ptr, FILE *file) { struct tm brokendown_time; @@ -140,7 +140,7 @@ for (i = 0; i < lease_hash_table->hash_size; i++) { element = lease_hash_table->hash_list[i]; while (element) { - if (write_lease((struct dhcp6_lease *)element->data, + if (write_6_lease((struct dhcp6_lease *)element->data, sync_file) < 0) { dprintf(LOG_ERR, "%s" "write lease failed", FNAME); return (NULL); @@ -152,7 +152,7 @@ struct dhcp6_lease *lv, *lv_next; for (lv = TAILQ_FIRST(&client6_iaidaddr.lease_list); lv; lv = lv_next) { lv_next = TAILQ_NEXT(lv, link); - if (write_lease(lv, sync_file) < 0) + if (write_6_lease(lv, sync_file) < 0) dprintf(LOG_ERR, "%s" "write lease failed", FNAME); } } @@ -354,8 +354,8 @@ get_linklocal(const char *ifname, struct in6_addr *linklocal) { - struct ifaddrs *ifa, *ifap; - struct sockaddr *sd; + struct ifaddrs *ifa=0, *ifap=0; + struct sockaddr *sd=0; if (getifaddrs(&ifap) < 0) { dprintf(LOG_ERR, "getifaddrs error"); return -1; --- dhcp-0.10/libdhcp6client/lease.h.libdhcp6client 2003-07-01 22:21:25.000000000 -0400 +++ dhcp-0.10/libdhcp6client/lease.h 2006-07-19 01:30:57.000000000 -0400 @@ -101,7 +101,7 @@ extern FILE *init_leases __P((const char *)); extern void lease_parse __P((FILE *)); extern int do_iaidaddr_hash __P((struct dhcp6_lease *, struct client6_if *)); -extern int write_lease __P((const struct dhcp6_lease *, FILE *)); +extern int write_6_lease __P((const struct dhcp6_lease *, FILE *)); extern FILE *sync_leases __P((FILE *, const char *, char *)); extern struct dhcp6_timer *syncfile_timo __P((void *)); extern unsigned int addr_hash __P((const void *)); --- /dev/null 2006-07-18 14:52:55.494029261 -0400 +++ dhcp-0.10/libdhcp6client/dhc6_alloc.c 2006-07-19 01:30:57.000000000 -0400 @@ -0,0 +1,67 @@ +#include <malloc.h> +#include <search.h> +extern void tdestroy (void *root, void (*free_node)(void *nodep)); +void *ifp_ptr; + +static void *ptr_tree=0L; + +static int ptr_comparator( const void *p1, const void *p2 ) +{ + return + ( (p1 == p2) + ? 0 + :( (p1 > p2) + ? 1 + : -1 + ) + ); +} + +void *dhc6_alloc( size_t s ) +{ + void *ptr = malloc( s ); + if ( ptr != 0 ) + tsearch(ptr, &(ptr_tree), ptr_comparator); + return ptr; +} + +void *dhc6_realloc( void *ptr, size_t s ) +{ + void *ptr2 = realloc(ptr, s); + if ( ptr2 != 0 ) + { + if ( ptr != 0 ) + tdelete(ptr,&(ptr_tree), ptr_comparator); + tsearch(ptr2, &(ptr_tree), ptr_comparator); + } + return ptr2; +} + +void *dhc6_calloc( size_t n, size_t s ) +{ + void *ptr = calloc( n, s ); + if ( ptr != 0 ) + tsearch(ptr, &(ptr_tree), ptr_comparator); + return ptr; +} + +char *dhc6_strdup( char *str ) +{ + char *ptr = strdup( str ); + if ( ptr != 0 ) + tsearch(ptr, &(ptr_tree), ptr_comparator); + return ptr; +} + +void dhc6_free( void *ptr ) +{ + free(ptr); + tdelete(ptr, &(ptr_tree), ptr_comparator); +} + +void dhc6_free_all_pointers(void) +{ + if( ptr_tree != 0L ) + tdestroy(ptr_tree, free); + ptr_tree = 0L; +} --- dhcp-0.10/libdhcp6client/common.c.libdhcp6client 2006-07-19 01:30:48.000000000 -0400 +++ dhcp-0.10/libdhcp6client/common.c 2006-07-19 01:30:57.000000000 -0400 @@ -79,11 +79,19 @@ #include "timer.h" #include "lease.h" +#ifdef LIBDHCP +#include "libdhcp_control.h" +#endif + int foreground; int debug_thresh; struct dhcp6_if *dhcp6_if; struct dns_list dnslist; +#ifdef LIBDHCP +struct host_conf *host_conflist; +#else static struct host_conf *host_conflist; +#endif static int in6_matchflags __P((struct sockaddr *, char *, int)); ssize_t gethwid __P((char *, int, const char *, u_int16_t *)); static int get_assigned_ipv6addrs __P((char *, char *, @@ -647,7 +655,7 @@ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name)); ifr.ifr_addr = *(struct sockaddr *)addr; - + dprintf(LOG_DEBUG,"in6_matchflags: SIOCGIFFLAGS"); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { warn("in6_matchflags: ioctl(SIOCGIFFLAGS, %s)", addr2str(addr, sizeof (addr->sa_data))); @@ -722,6 +730,9 @@ struct dhcp6_duid_type1 *dp; /* we only support the type1 DUID */ char tmpbuf[256]; /* DUID should be no more than 256 bytes */ +#ifdef LIBDHCP + if ( libdhcp_control && (libdhcp_control->capability & DHCP_USE_LEASE_DATABASE)) +#endif if ((fp = fopen(idfile, "r")) == NULL && errno != ENOENT) dprintf(LOG_NOTICE, "%s" "failed to open DUID file: %s", FNAME, idfile); @@ -776,6 +787,9 @@ } /* save the (new) ID to the file for next time */ +#ifdef LIBDHCP + if ( libdhcp_control && (libdhcp_control->capability & DHCP_USE_LEASE_DATABASE)) +#endif if (!fp) { if ((fp = fopen(idfile, "w+")) == NULL) { dprintf(LOG_ERR, "%s" @@ -823,8 +837,13 @@ return -1; strcpy(if_hwaddr.ifr_name, ifname); + dprintf(LOG_DEBUG,"gethwid: ioctl SIOCGIFHWADDR"); if (ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr) < 0) + { + close(skfd); return -1; + } + close(skfd); /* only support Ethernet */ switch (if_hwaddr.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: @@ -940,7 +959,7 @@ cp = (char *)(p + 1); np = (struct dhcp6opt *)(cp + optlen); - dprintf(LOG_DEBUG, "%s" "get DHCP option %s, len %d", + dprintf(LOG_INFO, "%s" "get DHCP option %s, len %d", FNAME, dhcp6optstr(opt), optlen); /* option length field overrun */ @@ -1085,7 +1104,7 @@ ntohl(*(u_int32_t *)(cp + sizeof(u_int32_t))); optinfo->iaidinfo.rebindtime = ntohl(*(u_int32_t *)(cp + 2 * sizeof(u_int32_t))); - dprintf(LOG_DEBUG, "get option iaid is %u, renewtime %u, " + dprintf(LOG_INFO, "get option iaid is %u, renewtime %u, " "rebindtime %u", optinfo->iaidinfo.iaid, optinfo->iaidinfo.renewtime, optinfo->iaidinfo.rebindtime); if (get_assigned_ipv6addrs(cp + 3 * sizeof(u_int32_t), @@ -1189,7 +1208,7 @@ opt = ntohs(opth.dh6opt_type); cp = p + sizeof(opth); np = cp + optlen; - dprintf(LOG_DEBUG, " IA address option: %s, " + dprintf(LOG_INFO, " IA address option: %s, " "len %d", dhcp6optstr(opt), optlen); if (np > ep) { @@ -1219,7 +1238,7 @@ } break; case DH6OPT_IADDR: - if (optlen < sizeof(ai) - sizeof(u_int32_t)) + if (optlen < sizeof(ai)- sizeof(u_int32_t)) goto malformed; memcpy(&ai, p, sizeof(ai)); /* copy the information into internal format */ @@ -2028,8 +2047,16 @@ va_list ap; char logbuf[LINE_MAX]; +#if LIBDHCP + va_start(ap, fmt); + if ( libdhcp_control && libdhcp_control->eh ) + libdhcp_control->eh(libdhcp_control, level, fmt, ap); + va_end(ap); + return; +#endif va_start(ap, fmt); vsnprintf(logbuf, sizeof(logbuf), fmt, ap); + va_end(ap); if (foreground && debug_thresh >= level) { time_t now; --- dhcp-0.10/libdhcp6client/dhcp6.h.libdhcp6client 2006-07-19 01:30:48.000000000 -0400 +++ dhcp-0.10/libdhcp6client/dhcp6.h 2006-07-19 01:30:57.000000000 -0400 @@ -116,9 +116,24 @@ typedef enum { IANA, IATA, IAPD} iatype_t; -typedef enum { ACTIVE, RENEW, +#ifdef LIBDHCP +typedef enum { DHCP6_ACTIVE=1, DHCP6_RENEW, + DHCP6_REBIND, DHCP6_EXPIRED, + DHCP6_INVALID } state_t; + +#define ACTIVE DHCP6_ACTIVE +#define RENEW DHCP6_RENEW +#define REBIND DHCP6_REBIND +#define EXPIRED DHCP6_EXPIRED +#define INVALID DHCP6_INVALID +#include <libdhcp_control.h> +extern LIBDHCP_Control *libdhcp_control; +#include <dhc6_alloc.h> +#else +typedef enum { ACTIVE=1, RENEW, REBIND, EXPIRED, INVALID } state_t; +#endif /* Internal data structure */ struct duid { --- /dev/null 2006-07-18 14:52:55.494029261 -0400 +++ dhcp-0.10/libdhcp6client/dhcp6client.h 2006-07-19 01:30:57.000000000 -0400 @@ -0,0 +1,22 @@ +/* dhcp6client.h + * + * Interface to the DHCPv6 client libdhcp6client library. + * + * + * Copyright(C) Jason Vas Dias <jvdias@redhat.com> Red Hat Inc. May 2006 + * + * 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 at + * http://www.fsf.org/licensing/licenses/gpl.txt + * and included in this software distribution as the "LICENSE" file. + * + * 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. + */ +struct libdhcp_control_s; /* include libdhcp_control.h or libdhcp.h for this */ + +extern int dhcpv6_client( struct libdhcp_control_s *dhc_ctl, int argc, char **argv, char **envp); +/* the DHCPv6 client main() function */