plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

BSD.c (2994B)


      1 #include <u.h>
      2 /* #include <everything_but_the_kitchen_sink.h> */
      3 #include <sys/socket.h>
      4 #include <netinet/in.h>
      5 #include <net/if.h>
      6 #include <sys/ioctl.h>
      7 #include <sys/sysctl.h>
      8 #include <net/ethernet.h>
      9 #include <net/if.h>
     10 #include <net/if_var.h>
     11 #include <net/if_dl.h>
     12 #include <net/if_types.h>
     13 #include <net/route.h>
     14 #include <netinet/in.h>
     15 #include <netinet/in_var.h>
     16 #include <arpa/inet.h>
     17 #include <netdb.h>
     18 #include <libc.h>
     19 #include <ip.h>
     20 
     21 static void
     22 sockaddr2ip(uchar *ip, struct sockaddr *sa)
     23 {
     24 	struct sockaddr_in *sin;
     25 
     26 	sin = (struct sockaddr_in*)sa;
     27 	memmove(ip, v4prefix, IPaddrlen);
     28 	memmove(ip+IPv4off, &sin->sin_addr, 4);
     29 }
     30 
     31 Ipifc*
     32 readipifc(char *net, Ipifc *ifc, int index)
     33 {
     34 	char *p, *ep, *q, *bp;
     35 	int i, mib[6];
     36 	size_t n;
     37 	Ipifc *list, **last;
     38 	Iplifc *lifc, **lastlifc;
     39 	struct if_msghdr *mh, *nmh;
     40 	struct ifa_msghdr *ah;
     41 	struct sockaddr *sa;
     42 	struct sockaddr_dl *sdl;
     43 	uchar ip[IPaddrlen];
     44 
     45 	USED(net);
     46 
     47 	free(ifc);
     48 	ifc = nil;
     49 	list = nil;
     50 	last = &list;
     51 
     52 	/*
     53 	 * Does not handle IPv6 yet.
     54 	 */
     55 
     56 	mib[0] = CTL_NET;
     57 	mib[1] = PF_ROUTE;
     58 	mib[2] = 0;
     59 	mib[3] = 0;
     60 	mib[4] = NET_RT_IFLIST;
     61 	mib[5] = 0;
     62 
     63 	n = 0;
     64 	if(sysctl(mib, 6, nil, &n, nil, 0) < 0)
     65 		return nil;
     66 	bp = mallocz(n, 1);
     67 	if(bp == nil)
     68 		return nil;
     69 	if(sysctl(mib, 6, bp, &n, nil, 0) < 0){
     70 		free(bp);
     71 		return nil;
     72 	}
     73 
     74 	p = bp;
     75 	ep = p+n;
     76 	while(p < ep){
     77 		mh = (struct if_msghdr*)p;
     78 		p += mh->ifm_msglen;
     79 		if(mh->ifm_type != RTM_IFINFO)
     80 			continue;
     81 		ifc = mallocz(sizeof *ifc, 1);
     82 		if(ifc == nil)
     83 			break;
     84 		*last = ifc;
     85 		last = &ifc->next;
     86 		sdl = (struct sockaddr_dl*)(mh+1);
     87 		n = sdl->sdl_nlen;
     88 		if(n >= sizeof ifc->dev)
     89 			n = sizeof ifc->dev - 1;
     90 		memmove(ifc->dev, sdl->sdl_data, n);
     91 		ifc->dev[n] = 0;
     92 		ifc->rp.linkmtu = mh->ifm_data.ifi_mtu;
     93 		lastlifc = &ifc->lifc;
     94 
     95 		if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6)
     96 			memmove(ifc->ether, LLADDR(sdl), 6);
     97 
     98 		while(p < ep){
     99 			ah = (struct ifa_msghdr*)p;
    100 			nmh = (struct if_msghdr*)p;
    101 			if(nmh->ifm_type != RTM_NEWADDR)
    102 				break;
    103 			p += nmh->ifm_msglen;
    104 			lifc = nil;
    105 			for(i=0, q=(char*)(ah+1); i<RTAX_MAX && q<p; i++){
    106 				if(!(ah->ifam_addrs & (1<<i)))
    107 					continue;
    108 				sa = (struct sockaddr*)q;
    109 				q += (sa->sa_len+sizeof(long)-1) & ~(sizeof(long)-1);
    110 				if(sa->sa_family != AF_INET)
    111 					continue;
    112 				if(lifc == nil){
    113 					lifc = mallocz(sizeof *lifc, 1);
    114 					if(lifc == nil)
    115 						continue;
    116 					*lastlifc = lifc;
    117 					lastlifc = &lifc->next;
    118 				}
    119 				sockaddr2ip(ip, sa);
    120 				switch(i){
    121 				case RTAX_IFA:
    122 					ipmove(lifc->ip, ip);
    123 					break;
    124 				case RTAX_NETMASK:
    125 					memset(ip, 0xFF, IPv4off);
    126 					ipmove(lifc->mask, ip);
    127 					break;
    128 				case RTAX_BRD:
    129 					if(mh->ifm_flags & IFF_POINTOPOINT)
    130 						/* ipmove(lifc->remote, ip) */ ;
    131 					if(mh->ifm_flags & IFF_BROADCAST)
    132 						/* ipmove(lifc->bcast, ip) */ ;
    133 					break;
    134 				case RTAX_GATEWAY:
    135 					break;
    136 				case RTAX_DST:
    137 					break;
    138 				}
    139 			}
    140 			if(lifc)
    141 				maskip(lifc->ip, lifc->mask, lifc->net);
    142 		}
    143 	}
    144 	free(bp);
    145 	return list;
    146 }