39#include <net/route.h> 40#include <net/if_dl.h> 41#include <netinet/in.h> 42#include <stdio.h> 43#include <fcntl.h> 44#ifdef __bsdi__ 45#include <kvm.h> 46#endif 47#include <net/if_types.h> 48#include <netinet/in_var.h> 49#include <netinet/if_ether.h> 50#include "log.h" 51 52#if RTM_VERSION >= 3 53#include <netinet/if_ether.h> 54#endif 55 56static int rtm_seq; 57 58static int get_ether_addr __P((int, u_long, struct sockaddr_dl *)); 59 60#define BCOPY(s, d, l) memcpy(d, s, l) 61#define BZERO(s, n) memset(s, 0, n) 62/* 63 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, 64 * if it exists. 65 */ 66#define SET_SA_FAMILY(addr, family) \ 67 BZERO((char *) &(addr), sizeof(addr)); \ 68 addr.sa_family = (family); \ 69 addr.sa_len = sizeof(addr); 70 71 72#if RTM_VERSION >= 3 73 74/* 75 * sifproxyarp - Make a proxy ARP entry for the peer. 76 */ 77static struct { 78 struct rt_msghdr hdr; 79 struct sockaddr_inarp dst; 80 struct sockaddr_dl hwa; 81 char extra[128]; 82} arpmsg; 83 84static int arpmsg_valid; 85 86int 87sifproxyarp(unit, hisaddr) 88 int unit; 89 u_long hisaddr; 90{ 91 int routes; 92 93 /* 94 * Get the hardware address of an interface on the same subnet 95 * as our local address. 96 */ 97 memset(&arpmsg, 0, sizeof(arpmsg)); 98 if (!get_ether_addr(unit, hisaddr, &arpmsg.hwa)) { 99 logprintf("Cannot determine ethernet address for proxy ARP\n"); 100 return 0; 101 } 102 103 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 104 logprintf("sifproxyarp: opening routing socket: \n"); 105 return 0; 106 } 107 108 arpmsg.hdr.rtm_type = RTM_ADD; 109 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; 110 arpmsg.hdr.rtm_version = RTM_VERSION; 111 arpmsg.hdr.rtm_seq = ++rtm_seq; 112 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 113 arpmsg.hdr.rtm_inits = RTV_EXPIRE; 114 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); 115 arpmsg.dst.sin_family = AF_INET; 116 arpmsg.dst.sin_addr.s_addr = hisaddr; 117 arpmsg.dst.sin_other = SIN_PROXY; 118 119 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg 120 + arpmsg.hwa.sdl_len; 121 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 122 logprintf("add proxy arp entry: \n"); 123 close(routes); 124 return 0; 125 } 126 127 close(routes); 128 arpmsg_valid = 1; 129 return 1; 130} 131 132/* 133 * cifproxyarp - Delete the proxy ARP entry for the peer. 134 */ 135int 136cifproxyarp(unit, hisaddr) 137 int unit; 138 u_long hisaddr; 139{ 140 int routes; 141 142 if (!arpmsg_valid) 143 return 0; 144 arpmsg_valid = 0; 145 146 arpmsg.hdr.rtm_type = RTM_DELETE; 147 arpmsg.hdr.rtm_seq = ++rtm_seq; 148 149 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 150 logprintf("sifproxyarp: opening routing socket: \n"); 151 return 0; 152 } 153 154 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 155 logprintf("delete proxy arp entry: \n"); 156 close(routes); 157 return 0; 158 } 159 160 close(routes); 161 return 1; 162} 163 164#else /* RTM_VERSION */ 165 166/* 167 * sifproxyarp - Make a proxy ARP entry for the peer. 168 */ 169int 170sifproxyarp(unit, hisaddr) 171 int unit; 172 u_long hisaddr; 173{ 174 struct arpreq arpreq; 175 struct { 176 struct sockaddr_dl sdl; 177 char space[128]; 178 } dls; 179 180 BZERO(&arpreq, sizeof(arpreq)); 181 182 /* 183 * Get the hardware address of an interface on the same subnet 184 * as our local address. 185 */ 186 if (!get_ether_addr(unit, hisaddr, &dls.sdl)) { 187 LogPrintf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n"); 188 return 0; 189 } 190 191 arpreq.arp_ha.sa_len = sizeof(struct sockaddr); 192 arpreq.arp_ha.sa_family = AF_UNSPEC; 193 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); 194 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 195 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 196 arpreq.arp_flags = ATF_PERM | ATF_PUBL; 197 if (ioctl(unit, SIOCSARP, (caddr_t)&arpreq) < 0) { 198 fprintf(stderr, "ioctl(SIOCSARP): \n"); 199 return 0; 200 } 201 202 return 1; 203} 204 205/* 206 * cifproxyarp - Delete the proxy ARP entry for the peer. 207 */ 208int 209cifproxyarp(unit, hisaddr) 210 int unit; 211 u_long hisaddr; 212{ 213 struct arpreq arpreq; 214 215 BZERO(&arpreq, sizeof(arpreq)); 216 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 217 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 218 if (ioctl(unit, SIOCDARP, (caddr_t)&arpreq) < 0) { 219 fprintf(stderr, "ioctl(SIOCDARP): \n"); 220 return 0; 221 } 222 return 1; 223} 224#endif /* RTM_VERSION */ 225 226 227/* 228 * get_ether_addr - get the hardware address of an interface on the 229 * the same subnet as ipaddr. 230 */ 231#define MAX_IFS 32 232 233int 234get_ether_addr(s, ipaddr, hwaddr) 235 int s; 236 u_long ipaddr; 237 struct sockaddr_dl *hwaddr; 238{ 239 struct ifreq *ifr, *ifend, *ifp; 240 u_long ina, mask; 241 struct sockaddr_dl *dla; 242 struct ifreq ifreq; 243 struct ifconf ifc; 244 struct ifreq ifs[MAX_IFS]; 245 246 ifc.ifc_len = sizeof(ifs); 247 ifc.ifc_req = ifs; 248 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { 249 fprintf(stderr, "ioctl(SIOCGIFCONF): \n"); 250 return 0; 251 } 252 253 /* 254 * Scan through looking for an interface with an Internet 255 * address on the same subnet as `ipaddr'. 256 */ 257 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 258 for (ifr = ifc.ifc_req; ifr < ifend; ) { 259 if (ifr->ifr_addr.sa_family == AF_INET) { 260 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 261 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 262 ifreq.ifr_name[sizeof(ifreq.ifr_name)-1]='\0'; 263 /* 264 * Check that the interface is up, and not point-to-point 265 * or loopback. 266 */ 267 if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) 268 continue; 269 if ((ifreq.ifr_flags & 270 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 271 != (IFF_UP|IFF_BROADCAST)) 272 goto nextif; 273 /* 274 * Get its netmask and check that it's on the right subnet. 275 */ 276 if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) 277 continue; 278 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 279 if ((ipaddr & mask) != (ina & mask)) 280 goto nextif; 281 282 break; 283 } 284nextif: 285 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 286 } 287 288 if (ifr >= ifend) 289 return 0; 290 LogPrintf(LOG_PHASE_BIT, "found interface %s for proxy arp\n", ifr->ifr_name); 291 292 /* 293 * Now scan through again looking for a link-level address 294 * for this interface. 295 */ 296 ifp = ifr; 297 for (ifr = ifc.ifc_req; ifr < ifend; ) { 298 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 299 && ifr->ifr_addr.sa_family == AF_LINK) { 300 /* 301 * Found the link-level address - copy it out 302 */ 303 dla = (struct sockaddr_dl *) &ifr->ifr_addr; 304#ifdef __bsdi__ 305 if (dla->sdl_alen == 0) 306 kmemgetether(ifr->ifr_name, dla); 307#endif 308 BCOPY(dla, hwaddr, dla->sdl_len); 309 return 1; 310 } 311 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 312 } 313 314 return 0; 315} 316 317#ifdef __bsdi__ 318#include <nlist.h> 319 320struct nlist nl[] = { 321#define N_IFNET 0 322 { "_ifnet" }, 323 "", 324}; 325 326 327kvm_t *kvmd; 328 329/* 330 * Read kernel memory, return 0 on success. 331 */ 332int 333kread(addr, buf, size) 334 u_long addr; 335 char *buf; 336 int size; 337{ 338 339 if (kvm_read(kvmd, addr, buf, size) != size) { 340 /* XXX this duplicates kvm_read's error printout */ 341 (void)fprintf(stderr, "kvm_read %s\n", 342 kvm_geterr(kvmd)); 343 return (-1); 344 } 345 return (0); 346} 347 348kmemgetether(ifname, dlo) 349char *ifname; 350struct sockaddr_dl *dlo; 351{ 352 struct ifnet ifnet; 353 int n; 354 u_long addr, ifaddraddr, ifnetfound, ifaddrfound; 355 char name[16+32]; 356 struct sockaddr *sa; 357 char *cp; 358 struct sockaddr_dl *sdl; 359 union { 360 struct ifaddr ifa; 361 struct in_ifaddr in; 362 } ifaddr; 363 struct arpcom ac; 364 365 kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); 366 if (kvmd) { 367 n = kvm_nlist(kvmd, nl); 368 if (n >= 0) { 369 addr = nl[N_IFNET].n_value; 370 kread(addr, (char *)&addr, sizeof(addr)); 371 ifaddraddr = ifnetfound = 0; 372 while (addr || ifaddraddr) { 373 ifnetfound = addr; 374 if (ifaddraddr == 0) { 375 if (kread(addr, (char *)&ifnet, sizeof(ifnet)) || 376 kread((u_long)ifnet.if_name, name, 16)) 377 return; 378 name[15] = 0; 379 addr = (u_long) ifnet.if_next; 380 cp = (char *)index(name, '\0'); 381 cp += sprintf(cp, "%d", ifnet.if_unit); 382 *cp = '\0'; 383 ifaddraddr = (u_long)ifnet.if_addrlist; 384 } 385 ifaddrfound = ifaddraddr; 386 if (ifaddraddr) { 387 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 388 ifaddraddr = 0; 389 continue; 390 } 391#define CP(x) ((char *)(x)) 392 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + CP(&ifaddr); 393 sa = (struct sockaddr *)cp; 394 if (sa->sa_family == AF_LINK && strcmp(ifname, name) == 0) { 395 sdl = (struct sockaddr_dl *)sa; 396 cp = (char *)LLADDR(sdl); 397 n = sdl->sdl_alen; 398 if (ifnet.if_type == IFT_ETHER) { 399 if (n == 0) { 400 kread(ifnetfound, (char *)&ac, sizeof(ac)); 401 cp = (char *)LLADDR(sdl); 402 bcopy((char *)ac.ac_enaddr, cp, 6); 403 sdl->sdl_alen = 6; 404 } 405 bcopy(sdl, dlo, sizeof(*sdl)); 406 return; 407 } 408 } 409 ifaddraddr = (u_long)ifaddr.ifa.ifa_next; 410 } 411 } 412 } 413 } 414} 415#endif 416 417#ifdef DEBUG 418main() 419{ 420 u_long ipaddr; 421 int s; 422 423 s = socket(AF_INET, SOCK_DGRAM, 0); 424 ipaddr = inet_addr("192.168.1.32"); 425 sifproxyarp(s, ipaddr); 426 close(s); 427} 428#endif
| 42#include <net/route.h> 43#include <net/if_dl.h> 44#include <netinet/in.h> 45#include <stdio.h> 46#include <fcntl.h> 47#ifdef __bsdi__ 48#include <kvm.h> 49#endif 50#include <net/if_types.h> 51#include <netinet/in_var.h> 52#include <netinet/if_ether.h> 53#include "log.h" 54 55#if RTM_VERSION >= 3 56#include <netinet/if_ether.h> 57#endif 58 59static int rtm_seq; 60 61static int get_ether_addr __P((int, u_long, struct sockaddr_dl *)); 62 63#define BCOPY(s, d, l) memcpy(d, s, l) 64#define BZERO(s, n) memset(s, 0, n) 65/* 66 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, 67 * if it exists. 68 */ 69#define SET_SA_FAMILY(addr, family) \ 70 BZERO((char *) &(addr), sizeof(addr)); \ 71 addr.sa_family = (family); \ 72 addr.sa_len = sizeof(addr); 73 74 75#if RTM_VERSION >= 3 76 77/* 78 * sifproxyarp - Make a proxy ARP entry for the peer. 79 */ 80static struct { 81 struct rt_msghdr hdr; 82 struct sockaddr_inarp dst; 83 struct sockaddr_dl hwa; 84 char extra[128]; 85} arpmsg; 86 87static int arpmsg_valid; 88 89int 90sifproxyarp(unit, hisaddr) 91 int unit; 92 u_long hisaddr; 93{ 94 int routes; 95 96 /* 97 * Get the hardware address of an interface on the same subnet 98 * as our local address. 99 */ 100 memset(&arpmsg, 0, sizeof(arpmsg)); 101 if (!get_ether_addr(unit, hisaddr, &arpmsg.hwa)) { 102 logprintf("Cannot determine ethernet address for proxy ARP\n"); 103 return 0; 104 } 105 106 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 107 logprintf("sifproxyarp: opening routing socket: \n"); 108 return 0; 109 } 110 111 arpmsg.hdr.rtm_type = RTM_ADD; 112 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; 113 arpmsg.hdr.rtm_version = RTM_VERSION; 114 arpmsg.hdr.rtm_seq = ++rtm_seq; 115 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 116 arpmsg.hdr.rtm_inits = RTV_EXPIRE; 117 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); 118 arpmsg.dst.sin_family = AF_INET; 119 arpmsg.dst.sin_addr.s_addr = hisaddr; 120 arpmsg.dst.sin_other = SIN_PROXY; 121 122 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg 123 + arpmsg.hwa.sdl_len; 124 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 125 logprintf("add proxy arp entry: \n"); 126 close(routes); 127 return 0; 128 } 129 130 close(routes); 131 arpmsg_valid = 1; 132 return 1; 133} 134 135/* 136 * cifproxyarp - Delete the proxy ARP entry for the peer. 137 */ 138int 139cifproxyarp(unit, hisaddr) 140 int unit; 141 u_long hisaddr; 142{ 143 int routes; 144 145 if (!arpmsg_valid) 146 return 0; 147 arpmsg_valid = 0; 148 149 arpmsg.hdr.rtm_type = RTM_DELETE; 150 arpmsg.hdr.rtm_seq = ++rtm_seq; 151 152 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 153 logprintf("sifproxyarp: opening routing socket: \n"); 154 return 0; 155 } 156 157 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 158 logprintf("delete proxy arp entry: \n"); 159 close(routes); 160 return 0; 161 } 162 163 close(routes); 164 return 1; 165} 166 167#else /* RTM_VERSION */ 168 169/* 170 * sifproxyarp - Make a proxy ARP entry for the peer. 171 */ 172int 173sifproxyarp(unit, hisaddr) 174 int unit; 175 u_long hisaddr; 176{ 177 struct arpreq arpreq; 178 struct { 179 struct sockaddr_dl sdl; 180 char space[128]; 181 } dls; 182 183 BZERO(&arpreq, sizeof(arpreq)); 184 185 /* 186 * Get the hardware address of an interface on the same subnet 187 * as our local address. 188 */ 189 if (!get_ether_addr(unit, hisaddr, &dls.sdl)) { 190 LogPrintf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n"); 191 return 0; 192 } 193 194 arpreq.arp_ha.sa_len = sizeof(struct sockaddr); 195 arpreq.arp_ha.sa_family = AF_UNSPEC; 196 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); 197 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 198 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 199 arpreq.arp_flags = ATF_PERM | ATF_PUBL; 200 if (ioctl(unit, SIOCSARP, (caddr_t)&arpreq) < 0) { 201 fprintf(stderr, "ioctl(SIOCSARP): \n"); 202 return 0; 203 } 204 205 return 1; 206} 207 208/* 209 * cifproxyarp - Delete the proxy ARP entry for the peer. 210 */ 211int 212cifproxyarp(unit, hisaddr) 213 int unit; 214 u_long hisaddr; 215{ 216 struct arpreq arpreq; 217 218 BZERO(&arpreq, sizeof(arpreq)); 219 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 220 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 221 if (ioctl(unit, SIOCDARP, (caddr_t)&arpreq) < 0) { 222 fprintf(stderr, "ioctl(SIOCDARP): \n"); 223 return 0; 224 } 225 return 1; 226} 227#endif /* RTM_VERSION */ 228 229 230/* 231 * get_ether_addr - get the hardware address of an interface on the 232 * the same subnet as ipaddr. 233 */ 234#define MAX_IFS 32 235 236int 237get_ether_addr(s, ipaddr, hwaddr) 238 int s; 239 u_long ipaddr; 240 struct sockaddr_dl *hwaddr; 241{ 242 struct ifreq *ifr, *ifend, *ifp; 243 u_long ina, mask; 244 struct sockaddr_dl *dla; 245 struct ifreq ifreq; 246 struct ifconf ifc; 247 struct ifreq ifs[MAX_IFS]; 248 249 ifc.ifc_len = sizeof(ifs); 250 ifc.ifc_req = ifs; 251 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { 252 fprintf(stderr, "ioctl(SIOCGIFCONF): \n"); 253 return 0; 254 } 255 256 /* 257 * Scan through looking for an interface with an Internet 258 * address on the same subnet as `ipaddr'. 259 */ 260 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 261 for (ifr = ifc.ifc_req; ifr < ifend; ) { 262 if (ifr->ifr_addr.sa_family == AF_INET) { 263 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 264 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 265 ifreq.ifr_name[sizeof(ifreq.ifr_name)-1]='\0'; 266 /* 267 * Check that the interface is up, and not point-to-point 268 * or loopback. 269 */ 270 if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) 271 continue; 272 if ((ifreq.ifr_flags & 273 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 274 != (IFF_UP|IFF_BROADCAST)) 275 goto nextif; 276 /* 277 * Get its netmask and check that it's on the right subnet. 278 */ 279 if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) 280 continue; 281 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 282 if ((ipaddr & mask) != (ina & mask)) 283 goto nextif; 284 285 break; 286 } 287nextif: 288 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 289 } 290 291 if (ifr >= ifend) 292 return 0; 293 LogPrintf(LOG_PHASE_BIT, "found interface %s for proxy arp\n", ifr->ifr_name); 294 295 /* 296 * Now scan through again looking for a link-level address 297 * for this interface. 298 */ 299 ifp = ifr; 300 for (ifr = ifc.ifc_req; ifr < ifend; ) { 301 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 302 && ifr->ifr_addr.sa_family == AF_LINK) { 303 /* 304 * Found the link-level address - copy it out 305 */ 306 dla = (struct sockaddr_dl *) &ifr->ifr_addr; 307#ifdef __bsdi__ 308 if (dla->sdl_alen == 0) 309 kmemgetether(ifr->ifr_name, dla); 310#endif 311 BCOPY(dla, hwaddr, dla->sdl_len); 312 return 1; 313 } 314 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 315 } 316 317 return 0; 318} 319 320#ifdef __bsdi__ 321#include <nlist.h> 322 323struct nlist nl[] = { 324#define N_IFNET 0 325 { "_ifnet" }, 326 "", 327}; 328 329 330kvm_t *kvmd; 331 332/* 333 * Read kernel memory, return 0 on success. 334 */ 335int 336kread(addr, buf, size) 337 u_long addr; 338 char *buf; 339 int size; 340{ 341 342 if (kvm_read(kvmd, addr, buf, size) != size) { 343 /* XXX this duplicates kvm_read's error printout */ 344 (void)fprintf(stderr, "kvm_read %s\n", 345 kvm_geterr(kvmd)); 346 return (-1); 347 } 348 return (0); 349} 350 351kmemgetether(ifname, dlo) 352char *ifname; 353struct sockaddr_dl *dlo; 354{ 355 struct ifnet ifnet; 356 int n; 357 u_long addr, ifaddraddr, ifnetfound, ifaddrfound; 358 char name[16+32]; 359 struct sockaddr *sa; 360 char *cp; 361 struct sockaddr_dl *sdl; 362 union { 363 struct ifaddr ifa; 364 struct in_ifaddr in; 365 } ifaddr; 366 struct arpcom ac; 367 368 kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); 369 if (kvmd) { 370 n = kvm_nlist(kvmd, nl); 371 if (n >= 0) { 372 addr = nl[N_IFNET].n_value; 373 kread(addr, (char *)&addr, sizeof(addr)); 374 ifaddraddr = ifnetfound = 0; 375 while (addr || ifaddraddr) { 376 ifnetfound = addr; 377 if (ifaddraddr == 0) { 378 if (kread(addr, (char *)&ifnet, sizeof(ifnet)) || 379 kread((u_long)ifnet.if_name, name, 16)) 380 return; 381 name[15] = 0; 382 addr = (u_long) ifnet.if_next; 383 cp = (char *)index(name, '\0'); 384 cp += sprintf(cp, "%d", ifnet.if_unit); 385 *cp = '\0'; 386 ifaddraddr = (u_long)ifnet.if_addrlist; 387 } 388 ifaddrfound = ifaddraddr; 389 if (ifaddraddr) { 390 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 391 ifaddraddr = 0; 392 continue; 393 } 394#define CP(x) ((char *)(x)) 395 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + CP(&ifaddr); 396 sa = (struct sockaddr *)cp; 397 if (sa->sa_family == AF_LINK && strcmp(ifname, name) == 0) { 398 sdl = (struct sockaddr_dl *)sa; 399 cp = (char *)LLADDR(sdl); 400 n = sdl->sdl_alen; 401 if (ifnet.if_type == IFT_ETHER) { 402 if (n == 0) { 403 kread(ifnetfound, (char *)&ac, sizeof(ac)); 404 cp = (char *)LLADDR(sdl); 405 bcopy((char *)ac.ac_enaddr, cp, 6); 406 sdl->sdl_alen = 6; 407 } 408 bcopy(sdl, dlo, sizeof(*sdl)); 409 return; 410 } 411 } 412 ifaddraddr = (u_long)ifaddr.ifa.ifa_next; 413 } 414 } 415 } 416 } 417} 418#endif 419 420#ifdef DEBUG 421main() 422{ 423 u_long ipaddr; 424 int s; 425 426 s = socket(AF_INET, SOCK_DGRAM, 0); 427 ipaddr = inet_addr("192.168.1.32"); 428 sifproxyarp(s, ipaddr); 429 close(s); 430} 431#endif
|