00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #include <sys/types.h>
00069 #include <unistd.h>
00070 #include <sys/ioctl.h>
00071 #include <sys/queue.h>
00072 #include <errno.h>
00073 #include <string.h>
00074 #include <assert.h>
00075 #include <pump.h>
00076 #include <netlink/netlink.h>
00077 #include <netlink/netlink-kernel.h>
00078
00079 #include <dhcp4client/dhcp4client.h>
00080 #include <dhcp4client/isc_dhcp/dhcpd.h>
00081
00082
00083 enum {
00084 OOM,
00085 DHCP_FAILED,
00086 };
00087
00088 static char * const pump_errors[] = {
00089 [OOM] = "out of memory",
00090 [DHCP_FAILED] = "DHCP configuration failed",
00091 NULL
00092 };
00093
00094 char * pumpSetupInterface(struct pumpNetIntf * ifx)
00095 {
00096 static char buf[512];
00097 NIC_t nic = 0;
00098 IPaddr_t addr = 0;
00099 IProute_t route = 0;
00100 int err=0;
00101 char *tag="";
00102
00103 if ( ifx->dhcp_nic )
00104 {
00105
00106 assert(ifx->dhcp_nic->nh);
00107
00108 int r = dhcp_nic_configure(ifx->dhcp_nic);
00109
00110 dhcp_nic_free(ifx->dhcp_nic);
00111 ifx->dhcp_nic = 0L;
00112 if ( r < 0 )
00113 {
00114 snprintf(buf, 512, "DHCP configuration failed - %d %s.",
00115 -r, strerror(-r)
00116 );
00117 relinquish_timeouts();
00118 return buf;
00119 }
00120 relinquish_timeouts();
00121 return NULL;
00122 }
00123
00124
00125
00126
00127 if (!ifx->nh) {
00128 ifx->nh = nic_open( 0 );
00129 if (!ifx->nh) {
00130 err = ENOMEM;
00131 tag = "nic_open";
00132 goto return_emsg;
00133 }
00134 }
00135
00136 nic = nic_by_name( ifx->nh, ifx->device );
00137 if ( nic == 0 )
00138 {
00139 err = ENODEV;
00140 tag = "get link";
00141 goto return_emsg;
00142 }
00143
00144 uint32_t flags = nic_get_flags( nic );
00145
00146 if ( flags & ( IFF_UP | IFF_RUNNING | IFF_BROADCAST ) )
00147 nic_set_flags(nic, flags | IFF_UP | IFF_RUNNING | IFF_BROADCAST);
00148
00149 if ( ( ifx->set & PUMP_INTFINFO_HAS_MTU ) && ( ifx->mtu ) )
00150 nic_set_mtu(nic, ifx->mtu);
00151
00152 tag = "set link";
00153 if ( (err = - nic_update ( nic )) > 0 )
00154 goto return_emsg;
00155
00156 if ( (ifx->ip.sa_family != AF_INET)
00157 &&(ifx->ip.sa_family != AF_INET6)
00158 ) goto return_ok;
00159
00160 addr = nic_addr( ifx->nh, ifx->ip );
00161 uint8_t prefix = 0;
00162 uint8_t isIPv4 = 0;
00163
00164 if ( addr == 0L )
00165 {
00166 err = ENOMEM;
00167 tag = "new addr";
00168 goto return_emsg;
00169 }
00170
00171 if( ifx->netmask.sa_family )
00172 switch( ifx->ip.sa_family )
00173 {
00174 case AF_INET:
00175
00176 isIPv4 = 1;
00177
00178 if ( ip_v4_addr( &(ifx->netmask) ) )
00179 {
00180 nic_addr_set_prefix
00181 ( addr,
00182 prefix = ip_v4_netmask_to_prefix( &(ifx->netmask) )
00183 );
00184 }
00185 break;
00186
00187 case AF_INET6:
00188
00189 if ( ifx->ipv6_prefixlen )
00190 {
00191 nic_addr_set_prefix
00192 ( addr,
00193 ifx->ipv6_prefixlen
00194 );
00195 }
00196 break;
00197 }
00198
00199 if ( ifx->broadcast.sa_family )
00200 nic_addr_set_broadcast
00201 (
00202 addr,
00203 ifx->broadcast
00204 );
00205 else
00206 if ( prefix && isIPv4 )
00207 nic_addr_set_broadcast
00208 (
00209 addr,
00210 ip_v4_broadcast( &(ifx->ip), prefix )
00211 );
00212
00213 tag = "create addr";
00214
00215 if( (err = - nic_add_address( nic, addr )) > 0 )
00216 goto return_emsg;
00217
00218
00219
00220
00221
00222 route = 0;
00223
00224 if( ifx->gateway.sa_family )
00225 {
00226 tag = "new route";
00227 route =
00228 nic_route_new
00229 ( ifx->nh,
00230 nic_get_index(nic),
00231 0L,0,
00232 &ifx->gateway,
00233 -1,
00234 -1,
00235 -1,
00236 -1,
00237 -1,
00238 0L,
00239 0L,
00240 0
00241 );
00242
00243 if( route == 0 )
00244 {
00245 err = ENOMEM;
00246 goto return_emsg;
00247 }
00248
00249 tag = "create route";
00250
00251 if((err = - nic_add_route( route )) > 0)
00252 goto return_emsg;
00253 }
00254
00255 return_ok:
00256 nic_close(&(ifx->nh));
00257 nic_addr_free(addr);
00258 nic_route_free(route);
00259
00260 relinquish_timeouts();
00261 return NULL;
00262
00263 return_emsg:
00264 nic_close(&ifx->nh);
00265 nic_addr_free(addr);
00266 nic_route_free(route);
00267
00268 snprintf(buf,512, "pumpSetupInterface failed: %s - %d: %s.",
00269 tag, err, strerror(err)
00270 );
00271
00272 relinquish_timeouts();
00273 return buf;
00274 }
00275
00276 extern int asprintf(char **strp, const char *fmt, ...);
00277
00278 static void
00279 ifxDHCPv6( struct pumpNetIntf * ifx )
00280 {
00281 IPaddr_t addr = STAILQ_FIRST( &(ifx->dhcp_nic->dhcpv6->address_list) )->addr;
00282 if( ifx->set & PUMP_INTFINFO_HAS_IP )
00283 {
00284 ifx->ipv6 = nic_ip_addr( addr );
00285 if( (ifx->ipv6_prefixlen = nic_addr_get_prefix( addr )) > 0 )
00286 ifx->set |= PUMP_INTFINFO_HAS_IPV6_PREFIX;
00287 ifx->set |= PUMP_INTFINFO_HAS_IPV6_IP;
00288 }else
00289 {
00290 ifx->ip = nic_ip_addr( addr );
00291 ifx->set |= PUMP_INTFINFO_HAS_IP;
00292 ifx->ipv6_prefixlen = nic_addr_get_prefix( addr );
00293 if ( ifx->ipv6_prefixlen )
00294 {
00295 ifx->network = ip_mask(&ifx->ip, ifx->ipv6_prefixlen);
00296 ifx->set |= PUMP_INTFINFO_HAS_NETWORK;
00297 }
00298 }
00299 if( !STAILQ_EMPTY(&(ifx->dhcp_nic->dhcpv6->dns_list)) )
00300 {
00301 IPaddr_list_node_t *n=0;
00302 STAILQ_FOREACH(n, &(ifx->dhcp_nic->dhcpv6->dns_list), link)
00303 {
00304 if( ifx->numDns >= MAX_DNS_SERVERS )
00305 break;
00306 ifx->dnsServers[ ifx->numDns++ ] = nic_ip_addr( n->addr );
00307 ifx->set |= PUMP_NETINFO_HAS_DNS;
00308 }
00309 }
00310 if( (ifx->set & PUMP_NETINFO_HAS_DNS)
00311 && ifx->dhcp_nic->dhcpv6->search_list
00312 )
00313 {
00314 char *s=ifx->domain;
00315 asprintf
00316 ( &(ifx->domain),
00317 "%s%s%s",
00318 s ? s : "",
00319 s ? " " : "" ,
00320 ifx->dhcp_nic->dhcpv6->search_list
00321 );
00322 if( s )
00323 free(s);
00324 ifx->set |= PUMP_NETINFO_HAS_DOMAIN;
00325 }
00326 }
00327
00328 static void
00329 ifxDHCPv4( struct pumpNetIntf *ifx )
00330 {
00331 IPaddr_t addr = STAILQ_FIRST( &(ifx->dhcp_nic->dhcpv4->address_list) )->addr;
00332 if( ifx->set & PUMP_INTFINFO_HAS_IP )
00333 {
00334 ifx->ipv4 = nic_ip_addr( addr );
00335 ifx->set |= PUMP_INTFINFO_HAS_IPV4_IP;
00336 }else
00337 {
00338 ifx->ip = nic_ip_addr( addr );
00339 ifx->set |= PUMP_INTFINFO_HAS_IP;
00340 if ( nic_addr_get_prefix( addr ) )
00341 {
00342 ifx->network = ip_mask(&ifx->ip, nic_addr_get_prefix( addr ) );
00343 ifx->set |= PUMP_INTFINFO_HAS_NETWORK;
00344 }
00345 }
00346 if ( nic_addr_get_prefix( addr ) )
00347 {
00348 ifx->netmask = ip_v4_prefix_to_netmask( nic_addr_get_prefix( addr ) );
00349 ifx->set |= PUMP_INTFINFO_HAS_NETMASK;
00350
00351 ip_addr_t broadcast = nic_addr_get_broadcast( addr );
00352 if( broadcast.sa_family )
00353 {
00354 ifx->broadcast = broadcast;
00355 ifx->set |= PUMP_INTFINFO_HAS_BROADCAST;
00356 }
00357 }
00358 if( ifx->dhcp_nic->dhcpv4
00359 &&( !STAILQ_EMPTY( &( ifx->dhcp_nic->dhcpv4->route_list )) )
00360 )
00361 {
00362 IProute_list_node_t *n;
00363 STAILQ_FOREACH( n, &( ifx->dhcp_nic->dhcpv4->route_list ), link )
00364 {
00365 ip_addr_t dst = nic_route_get_dst( n->route );
00366 ip_addr_t gw = nic_route_get_gateway( n->route );
00367 uint8_t dst_len = nic_route_get_dst_len( n->route );
00368 if( (dst.sa_family == 0)
00369 &&(dst_len == 0)
00370 &&(gw.sa_family == AF_INET)
00371 )
00372 {
00373 ifx->gateway = gw;
00374 ifx->set |= PUMP_NETINFO_HAS_GATEWAY;
00375 break;
00376 }
00377 }
00378 }
00379 if( ifx->dhcp_nic->dhc4ctl
00380 && dhcpv4_mtu_option( ifx->dhcp_nic->dhc4ctl )
00381 )
00382 {
00383 ifx->mtu = dhcpv4_mtu_option( ifx->dhcp_nic->dhc4ctl );
00384 ifx->set |= PUMP_INTFINFO_HAS_MTU;
00385 }
00386 if( ifx->dhcp_nic->dhcpv4->lease.dhcp4_lease )
00387 {
00388 DHCPv4_lease *lease=ifx->dhcp_nic->dhcpv4->lease.dhcp4_lease;
00389 if ( lease->server_address.s_addr != 0 )
00390 {
00391 ifx->nextServer = ip_addr_in(&(lease->server_address));
00392 ifx->set |= PUMP_INTFINFO_HAS_NEXTSERVER;
00393 }
00394 if ( lease->filename )
00395 {
00396 ifx->bootFile = strdup( lease->filename );
00397 ifx->set |= PUMP_INTFINFO_HAS_BOOTFILE;
00398 }
00399 }
00400
00401 if( !STAILQ_EMPTY(&(ifx->dhcp_nic->dhcpv4->dns_list)) )
00402 {
00403 IPaddr_list_node_t *n=0;
00404 STAILQ_FOREACH(n, &(ifx->dhcp_nic->dhcpv4->dns_list), link)
00405 {
00406 if( ifx->numDns >= MAX_DNS_SERVERS )
00407 break;
00408 ifx->dnsServers[ ifx->numDns++ ] = nic_ip_addr( n->addr );
00409 ifx->set |= PUMP_NETINFO_HAS_DNS;
00410 }
00411 }
00412 if( (ifx->set & PUMP_NETINFO_HAS_DNS)
00413 && ifx->dhcp_nic->dhcpv4->search_list
00414 )
00415 {
00416 char *s=ifx->domain;
00417 asprintf
00418 ( &(ifx->domain),
00419 "%s%s%s",
00420 s ? s : "",
00421 s ? " " : "" ,
00422 ifx->dhcp_nic->dhcpv4->search_list
00423 );
00424 if( s )
00425 free(s);
00426 ifx->set |= PUMP_NETINFO_HAS_DOMAIN;
00427 }
00428 if( ifx->dhcp_nic->dhcpv4->host_name )
00429 {
00430 ifx->set |= PUMP_NETINFO_HAS_HOSTNAME;
00431 if(ifx->hostname)
00432 free(ifx->hostname);
00433 ifx->hostname = strdup( ifx->dhcp_nic->dhcpv4->host_name );
00434 }
00435 }
00436
00437 char * pumpDhcpClassRun
00438 ( struct pumpNetIntf * ifx,
00439 char * hostname,
00440 char * vendor_class,
00441 DHCP_Preference dhcp_preference ,
00442 LIBDHCP_Capability dhcp_capability ,
00443 time_t timeout,
00444 void (*logger)(void*,int,char*,va_list),
00445 int log_level
00446 )
00447 {
00448 assert(!ifx->nh);
00449
00450 if (!(ifx->nh = nic_open(NETLINK_ROUTE)))
00451 return pump_errors[OOM];
00452
00453 if ( logger )
00454 {
00455 nic_set_va_logger(ifx->nh, (NIC_VA_Error_Handler_t)logger, &ifx);
00456 nic_set_loglevel(ifx->nh, log_level );
00457 }
00458 ifx->dhcp_nic =
00459 dhcp_nic
00460 (
00461 ifx->nh,
00462 dhcp_preference,
00463 ifx->device,
00464 dhcp_capability,
00465 timeout,
00466 (LIBDHCP_Error_Handler)logger,
00467 log_level,
00468 "-V", vendor_class,
00469 hostname ? "-H" : 0L,
00470 hostname ? hostname : 0L,
00471 0L
00472 );
00473 if ( ifx->dhcp_nic )
00474 {
00475
00476
00477
00478
00479 if ( ( ifx->dhcp_nic->dhcpv4 && ifx->dhcp_nic->dhcpv6 )
00480 &&( !STAILQ_EMPTY( &( ifx->dhcp_nic->dhcpv4->address_list )) )
00481 &&( !STAILQ_EMPTY( &( ifx->dhcp_nic->dhcpv6->address_list )) )
00482 )
00483 {
00484 if ( dhcp_preference & IPv6_PREFERENCE )
00485 {
00486 ifxDHCPv6( ifx );
00487 ifxDHCPv4( ifx );
00488 }else
00489 {
00490 ifxDHCPv4( ifx );
00491 ifxDHCPv6( ifx );
00492 }
00493 }else
00494 if( ifx->dhcp_nic->dhcpv4
00495 &&( !STAILQ_EMPTY( &( ifx->dhcp_nic->dhcpv4->address_list )) )
00496 )
00497 {
00498 ifxDHCPv4( ifx );
00499 }else
00500 if( ifx->dhcp_nic->dhcpv6
00501 &&( !STAILQ_EMPTY( &( ifx->dhcp_nic->dhcpv6->address_list )) )
00502 )
00503 {
00504 ifxDHCPv6( ifx );
00505 }
00506 ifx->nh = NULL;
00507 }else
00508 {
00509 nic_close(&ifx->nh);
00510 return pump_errors[DHCP_FAILED];
00511 }
00512 return NULL;
00513 }
00514
00515 char * pumpDisableInterface(char * device)
00516 {
00517 static char buf[512];
00518 struct ifreq req;
00519 int s, e;
00520
00521 s = socket(AF_INET, SOCK_DGRAM, 0);
00522
00523 memset(&req,0,sizeof(req));
00524
00525 strcpy(req.ifr_name, device);
00526 if (ioctl(s, SIOCGIFFLAGS, &req)) {
00527 e = errno;
00528 snprintf(buf, 512,
00529 "ioctl SIOCGIFFLAGS failed: %d %s\n",
00530 e, strerror(e)
00531 );
00532 close(s);
00533 return &(buf[0]);
00534 }
00535
00536 req.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
00537 if (ioctl(s, SIOCSIFFLAGS, &req)) {
00538 e = errno;
00539 snprintf(buf, 512,
00540 "ioctl SIOCSIFFLAGS failed: %d %s\n",
00541 e, strerror(e)
00542 );
00543 close(s);
00544 return &(buf[0]);
00545 }
00546
00547 close(s);
00548
00549 return NULL;
00550 }
00551
00552
00553
00554