Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/networking/zcip.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/networking/zcip.c
r3232 r3621 31 31 //usage: "\n -q Quit after obtaining address" 32 32 //usage: "\n -r 169.254.x.x Request this address first" 33 //usage: "\n -l x.x.0.0 Use this range instead of 169.254" 33 34 //usage: "\n -v Verbose" 35 //usage: "\n" 36 //usage: "\n$LOGGING=none Suppress logging" 37 //usage: "\n$LOGGING=syslog Log to syslog" 34 38 //usage: "\n" 35 39 //usage: "\nWith no -q, runs continuously monitoring for ARP conflicts," … … 37 41 38 42 #include "libbb.h" 43 #include "common_bufsiz.h" 39 44 #include <netinet/ether.h> 40 45 #include <net/if.h> … … 53 58 54 59 enum { 55 /* 169.254.0.0 */ 56 LINKLOCAL_ADDR = 0xa9fe0000, 57 58 /* protocol timeout parameters, specified in seconds */ 60 /* 0-1 seconds before sending 1st probe */ 59 61 PROBE_WAIT = 1, 62 /* 1-2 seconds between probes */ 60 63 PROBE_MIN = 1, 61 64 PROBE_MAX = 2, 62 PROBE_NUM = 3, 63 MAX_CONFLICTS = 10,64 RATE_LIMIT_INTERVAL = 60,65 ANNOUNCE_WAIT = 2,66 ANNOUNCE_NUM= 2,67 ANNOUNCE_INTERVAL = 2,68 DEFEND_INTERVAL = 10 65 PROBE_NUM = 3, /* total probes to send */ 66 ANNOUNCE_INTERVAL = 2, /* 2 seconds between announces */ 67 ANNOUNCE_NUM = 3, /* announces to send */ 68 /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */ 69 CONFLICT_MULTIPLIER = 2, 70 /* if we monitor and see a conflict, how long is defend state? */ 71 DEFEND_INTERVAL = 10, 69 72 }; 70 73 … … 72 75 enum { 73 76 PROBE = 0, 74 RATE_LIMIT_PROBE,75 77 ANNOUNCE, 76 78 MONITOR, … … 86 88 87 89 struct globals { 88 struct sockaddr saddr; 89 struct ether_addr eth_addr; 90 struct sockaddr iface_sockaddr; 91 struct ether_addr our_ethaddr; 92 uint32_t localnet_ip; 90 93 } FIX_ALIASING; 91 #define G (*(struct globals*)&bb_common_bufsiz1) 92 #define saddr (G.saddr ) 93 #define eth_addr (G.eth_addr) 94 #define INIT_G() do { } while (0) 94 #define G (*(struct globals*)bb_common_bufsiz1) 95 #define INIT_G() do { setup_common_bufsiz(); } while (0) 95 96 96 97 … … 99 100 * the first and last 256 addresses are reserved. 100 101 */ 101 static uint32_t pick (void)102 static uint32_t pick_nip(void) 102 103 { 103 104 unsigned tmp; … … 106 107 tmp = rand() & IN_CLASSB_HOST; 107 108 } while (tmp > (IN_CLASSB_HOST - 0x0200)); 108 return htonl((LINKLOCAL_ADDR + 0x0100) + tmp); 109 return htonl((G.localnet_ip + 0x0100) + tmp); 110 } 111 112 static const char *nip_to_a(uint32_t nip) 113 { 114 struct in_addr in; 115 in.s_addr = nip; 116 return inet_ntoa(in); 109 117 } 110 118 … … 112 120 * Broadcast an ARP packet. 113 121 */ 114 static void arp(122 static void send_arp_request( 115 123 /* int op, - always ARPOP_REQUEST */ 116 /* const struct ether_addr *source_eth, - always & eth_addr */117 struct in_addr source_ip,118 const struct ether_addr *target_eth, struct in_addr target_ip)124 /* const struct ether_addr *source_eth, - always &G.our_ethaddr */ 125 uint32_t source_nip, 126 const struct ether_addr *target_eth, uint32_t target_nip) 119 127 { 120 128 enum { op = ARPOP_REQUEST }; 121 #define source_eth (& eth_addr)129 #define source_eth (&G.our_ethaddr) 122 130 123 131 struct arp_packet p; … … 136 144 p.arp.arp_op = htons(op); 137 145 memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); 138 memcpy(&p.arp.arp_spa, &source_ ip, sizeof(p.arp.arp_spa));146 memcpy(&p.arp.arp_spa, &source_nip, 4); 139 147 memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); 140 memcpy(&p.arp.arp_tpa, &target_ ip, sizeof(p.arp.arp_tpa));148 memcpy(&p.arp.arp_tpa, &target_nip, 4); 141 149 142 150 // send it 143 // Even though sock_fd is already bound to saddr, just send()151 // Even though sock_fd is already bound to G.iface_sockaddr, just send() 144 152 // won't work, because "socket is not connected" 145 153 // (and connect() won't fix that, "operation not supported"). 146 // Thus we sendto() to saddr. I wonder which sockaddr154 // Thus we sendto() to G.iface_sockaddr. I wonder which sockaddr 147 155 // (from bind() or from sendto()?) kernel actually uses 148 156 // to determine iface to emit the packet from... 149 xsendto(sock_fd, &p, sizeof(p), & saddr, sizeof(saddr));157 xsendto(sock_fd, &p, sizeof(p), &G.iface_sockaddr, sizeof(G.iface_sockaddr)); 150 158 #undef source_eth 151 159 } … … 155 163 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL 156 164 */ 157 static int run(char *argv[3], const char *param, struct in_addr *ip)165 static int run(char *argv[3], const char *param, uint32_t nip) 158 166 { 159 167 int status; 160 c har *addr = addr; /* for gcc */168 const char *addr = addr; /* for gcc */ 161 169 const char *fmt = "%s %s %s" + 3; 162 170 … … 165 173 VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]); 166 174 167 if ( ip) {168 addr = inet_ntoa(*ip);175 if (nip != 0) { 176 addr = nip_to_a(nip); 169 177 xsetenv("ip", addr); 170 178 fmt -= 3; 171 179 } 172 bb_ info_msg(fmt, argv[2], argv[0], addr);180 bb_error_msg(fmt, argv[2], argv[0], addr); 173 181 174 182 status = spawn_and_wait(argv + 1); … … 187 195 static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs) 188 196 { 189 return rand() % (secs * 1000);197 return (unsigned)rand() % (secs * 1000); 190 198 } 191 199 … … 196 204 int zcip_main(int argc UNUSED_PARAM, char **argv) 197 205 { 206 char *r_opt; 207 const char *l_opt = "169.254.0.0"; 198 208 int state; 199 char *r_opt;209 int nsent; 200 210 unsigned opts; 201 211 202 // ugly trick, but I want these zeroed in one go212 // Ugly trick, but I want these zeroed in one go 203 213 struct { 204 const struct in_addr null_ip; 205 const struct ether_addr null_addr; 206 struct in_addr ip; 214 const struct ether_addr null_ethaddr; 207 215 struct ifreq ifr; 208 int timeout_ms; /* must be signed */ 209 unsigned conflicts; 210 unsigned nprobes; 211 unsigned nclaims; 212 int ready; 216 uint32_t chosen_nip; 217 int conflicts; 218 int timeout_ms; // must be signed 213 219 int verbose; 214 220 } L; 215 #define null_ip (L.null_ip ) 216 #define null_addr (L.null_addr ) 217 #define ip (L.ip ) 218 #define ifr (L.ifr ) 219 #define timeout_ms (L.timeout_ms) 220 #define conflicts (L.conflicts ) 221 #define nprobes (L.nprobes ) 222 #define nclaims (L.nclaims ) 223 #define ready (L.ready ) 224 #define verbose (L.verbose ) 221 #define null_ethaddr (L.null_ethaddr) 222 #define ifr (L.ifr ) 223 #define chosen_nip (L.chosen_nip ) 224 #define conflicts (L.conflicts ) 225 #define timeout_ms (L.timeout_ms ) 226 #define verbose (L.verbose ) 225 227 226 228 memset(&L, 0, sizeof(L)); … … 229 231 #define FOREGROUND (opts & 1) 230 232 #define QUIT (opts & 2) 231 // parse commandline: prog [options] ifname script233 // Parse commandline: prog [options] ifname script 232 234 // exactly 2 args; -v accumulates and implies -f 233 235 opt_complementary = "=2:vv:vf"; 234 opts = getopt32(argv, "fqr: v", &r_opt, &verbose);236 opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose); 235 237 #if !BB_MMU 236 238 // on NOMMU reexec early (or else we will rerun things twice) … … 238 240 bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv); 239 241 #endif 240 // open an ARP socket242 // Open an ARP socket 241 243 // (need to do it before openlog to prevent openlog from taking 242 244 // fd 3 (sock_fd==3)) … … 247 249 logmode |= LOGMODE_SYSLOG; 248 250 } 251 bb_logenv_override(); 252 253 { // -l n.n.n.n 254 struct in_addr net; 255 if (inet_aton(l_opt, &net) == 0 256 || (net.s_addr & htonl(IN_CLASSB_NET)) != net.s_addr 257 ) { 258 bb_error_msg_and_die("invalid network address"); 259 } 260 G.localnet_ip = ntohl(net.s_addr); 261 } 249 262 if (opts & 4) { // -r n.n.n.n 263 struct in_addr ip; 250 264 if (inet_aton(r_opt, &ip) == 0 251 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR265 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip 252 266 ) { 253 267 bb_error_msg_and_die("invalid link address"); 254 268 } 269 chosen_nip = ip.s_addr; 255 270 } 256 271 argv += optind - 1; … … 265 280 xsetenv("interface", argv_intf); 266 281 267 // initialize the interface (modprobe, ifup, etc)268 if (run(argv, "init", NULL))282 // Initialize the interface (modprobe, ifup, etc) 283 if (run(argv, "init", 0)) 269 284 return EXIT_FAILURE; 270 285 271 // initialize saddr272 // saddr is: { u16 sa_family; u8 sa_data[14]; }273 //memset(& saddr, 0, sizeof(saddr));286 // Initialize G.iface_sockaddr 287 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; } 288 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr)); 274 289 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! 275 safe_strncpy( saddr.sa_data, argv_intf, sizeof(saddr.sa_data));276 277 // bind to the interface's ARP socket278 xbind(sock_fd, & saddr, sizeof(saddr));279 280 // get the interface's ethernet address290 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data)); 291 292 // Bind to the interface's ARP socket 293 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr)); 294 295 // Get the interface's ethernet address 281 296 //memset(&ifr, 0, sizeof(ifr)); 282 297 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); 283 298 xioctl(sock_fd, SIOCGIFHWADDR, &ifr); 284 memcpy(& eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);285 286 // start with some stable ip address, either a function of299 memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 300 301 // Start with some stable ip address, either a function of 287 302 // the hardware address or else the last address we used. 288 303 // we are taking low-order four bytes, as top-order ones … … 292 307 { 293 308 uint32_t t; 294 move_from_unaligned32(t, ((char *)& eth_addr + 2));309 move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2)); 295 310 srand(t); 296 311 } 297 if (ip.s_addr == 0)298 ip.s_addr = pick();299 300 312 // FIXME cases to handle: 301 313 // - zcip already running! 302 314 // - link already has local address... just defend/update 303 315 304 // daemonize now; don't delay system startup316 // Daemonize now; don't delay system startup 305 317 if (!FOREGROUND) { 306 318 #if BB_MMU 307 319 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); 308 320 #endif 309 bb_ info_msg("start, interface %s", argv_intf);310 } 311 312 // run the dynamic address negotiation protocol,321 bb_error_msg("start, interface %s", argv_intf); 322 } 323 324 // Run the dynamic address negotiation protocol, 313 325 // restarting after address conflicts: 314 326 // - start with some address we want to try 315 327 // - short random delay 316 328 // - arp probes to see if another host uses it 329 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 tell 0.0.0.0 317 330 // - arp announcements that we're claiming it 331 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 318 332 // - use it 319 333 // - defend it, within limits … … 323 337 // - poll error (when does this happen?) 324 338 // - read error (when does this happen?) 325 // - sendto error (in arp()) (when does this happen?)339 // - sendto error (in send_arp_request()) (when does this happen?) 326 340 // - revents & POLLERR (link down). run "<script> deconfig" first 341 if (chosen_nip == 0) { 342 new_nip_and_PROBE: 343 chosen_nip = pick_nip(); 344 } 345 nsent = 0; 327 346 state = PROBE; 328 347 while (1) { 329 348 struct pollfd fds[1]; 330 unsigned deadline_us ;349 unsigned deadline_us = deadline_us; 331 350 struct arp_packet p; 332 int source_ip_conflict;333 int target_ip_conflict;351 int ip_conflict; 352 int n; 334 353 335 354 fds[0].fd = sock_fd; … … 337 356 fds[0].revents = 0; 338 357 339 // poll, being ready to adjust current timeout358 // Poll, being ready to adjust current timeout 340 359 if (!timeout_ms) { 341 360 timeout_ms = random_delay_ms(PROBE_WAIT); … … 344 363 // ones we'd care about. 345 364 } 346 // set deadline_us to the point in time when we timeout 347 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 348 349 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", 350 timeout_ms, argv_intf, nprobes, nclaims); 351 352 switch (safe_poll(fds, 1, timeout_ms)) { 353 354 default: 365 if (timeout_ms >= 0) { 366 // Set deadline_us to the point in time when we timeout 367 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 368 } 369 370 VDBG("...wait %d %s nsent=%u\n", 371 timeout_ms, argv_intf, nsent); 372 373 n = safe_poll(fds, 1, timeout_ms); 374 if (n < 0) { 355 375 //bb_perror_msg("poll"); - done in safe_poll 356 376 return EXIT_FAILURE; 357 358 // timeout 359 case 0: 360 VDBG("state = %d\n", state); 377 } 378 if (n == 0) { // timed out? 379 VDBG("state:%d\n", state); 361 380 switch (state) { 362 381 case PROBE: 363 // timeouts in the PROBE state mean no conflicting ARP packets364 // have been received, sowe can progress through the states365 if (n probes< PROBE_NUM) {366 n probes++;382 // No conflicting ARP packets were seen: 383 // we can progress through the states 384 if (nsent < PROBE_NUM) { 385 nsent++; 367 386 VDBG("probe/%u %s@%s\n", 368 nprobes, argv_intf, inet_ntoa(ip)); 369 arp(/* ARPOP_REQUEST, */ 370 /* ð_addr, */ null_ip, 371 &null_addr, ip); 387 nsent, argv_intf, nip_to_a(chosen_nip)); 372 388 timeout_ms = PROBE_MIN * 1000; 373 389 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); 390 send_arp_request(0, &null_ethaddr, chosen_nip); 391 continue; 374 392 } 375 else { 376 // Switch to announce state. 377 state = ANNOUNCE; 378 nclaims = 0; 393 // Switch to announce state 394 nsent = 0; 395 state = ANNOUNCE; 396 goto send_announce; 397 case ANNOUNCE: 398 // No conflicting ARP packets were seen: 399 // we can progress through the states 400 if (nsent < ANNOUNCE_NUM) { 401 send_announce: 402 nsent++; 379 403 VDBG("announce/%u %s@%s\n", 380 nclaims, argv_intf, inet_ntoa(ip)); 381 arp(/* ARPOP_REQUEST, */ 382 /* ð_addr, */ ip, 383 ð_addr, ip); 404 nsent, argv_intf, nip_to_a(chosen_nip)); 384 405 timeout_ms = ANNOUNCE_INTERVAL * 1000; 406 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip); 407 continue; 385 408 } 386 break; 387 case RATE_LIMIT_PROBE: 388 // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets 389 // have been received, so we can move immediately to the announce state 390 state = ANNOUNCE; 391 nclaims = 0; 392 VDBG("announce/%u %s@%s\n", 393 nclaims, argv_intf, inet_ntoa(ip)); 394 arp(/* ARPOP_REQUEST, */ 395 /* ð_addr, */ ip, 396 ð_addr, ip); 397 timeout_ms = ANNOUNCE_INTERVAL * 1000; 398 break; 399 case ANNOUNCE: 400 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 401 // have been received, so we can progress through the states 402 if (nclaims < ANNOUNCE_NUM) { 403 nclaims++; 404 VDBG("announce/%u %s@%s\n", 405 nclaims, argv_intf, inet_ntoa(ip)); 406 arp(/* ARPOP_REQUEST, */ 407 /* ð_addr, */ ip, 408 ð_addr, ip); 409 timeout_ms = ANNOUNCE_INTERVAL * 1000; 410 } 411 else { 412 // Switch to monitor state. 413 state = MONITOR; 414 // link is ok to use earlier 415 // FIXME update filters 416 run(argv, "config", &ip); 417 ready = 1; 418 conflicts = 0; 419 timeout_ms = -1; // Never timeout in the monitor state. 420 421 // NOTE: all other exit paths 422 // should deconfig ... 423 if (QUIT) 424 return EXIT_SUCCESS; 425 } 426 break; 427 case DEFEND: 428 // We won! No ARP replies, so just go back to monitor. 409 // Switch to monitor state 410 // FIXME update filters 411 run(argv, "config", chosen_nip); 412 // NOTE: all other exit paths should deconfig... 413 if (QUIT) 414 return EXIT_SUCCESS; 415 // fall through: switch to MONITOR 416 default: 417 // case DEFEND: 418 // case MONITOR: (shouldn't happen, MONITOR timeout is infinite) 419 // Defend period ended with no ARP replies - we won 420 timeout_ms = -1; // never timeout in monitor state 429 421 state = MONITOR; 430 timeout_ms = -1;431 conflicts = 0;432 break;433 default:434 // Invalid, should never happen. Restart the whole protocol.435 state = PROBE;436 ip.s_addr = pick();437 timeout_ms = 0;438 nprobes = 0;439 nclaims = 0;440 break;441 } // switch (state)442 break; // case 0 (timeout)443 444 // packets arriving, or link went down445 case 1:446 // We need to adjust the timeout in case we didn't receive447 // a conflicting packet.448 if (timeout_ms > 0) {449 unsigned diff = deadline_us - MONOTONIC_US();450 if ((int)(diff) < 0) {451 // Current time is greater than the expected timeout time.452 // Should never happen.453 VDBG("missed an expected timeout\n");454 timeout_ms = 0;455 } else {456 VDBG("adjusting timeout\n");457 timeout_ms = (diff / 1000) | 1; /* never 0 */458 }459 }460 461 if ((fds[0].revents & POLLIN) == 0) {462 if (fds[0].revents & POLLERR) {463 // FIXME: links routinely go down;464 // this shouldn't necessarily exit.465 bb_error_msg("iface %s is down", argv_intf);466 if (ready) {467 run(argv, "deconfig", &ip);468 }469 return EXIT_FAILURE;470 }471 422 continue; 472 423 } 473 474 // read ARP packet 475 if (safe_read(sock_fd, &p, sizeof(p)) < 0) { 476 bb_perror_msg_and_die(bb_msg_read_error); 424 } 425 426 // Packet arrived, or link went down. 427 // We need to adjust the timeout in case we didn't receive 428 // a conflicting packet. 429 if (timeout_ms > 0) { 430 unsigned diff = deadline_us - MONOTONIC_US(); 431 if ((int)(diff) < 0) { 432 // Current time is greater than the expected timeout time. 433 diff = 0; 477 434 } 478 if (p.eth.ether_type != htons(ETHERTYPE_ARP)) 479 continue; 435 VDBG("adjusting timeout\n"); 436 timeout_ms = (diff / 1000) | 1; // never 0 437 } 438 439 if ((fds[0].revents & POLLIN) == 0) { 440 if (fds[0].revents & POLLERR) { 441 // FIXME: links routinely go down; 442 // this shouldn't necessarily exit. 443 bb_error_msg("iface %s is down", argv_intf); 444 if (state >= MONITOR) { 445 // Only if we are in MONITOR or DEFEND 446 run(argv, "deconfig", chosen_nip); 447 } 448 return EXIT_FAILURE; 449 } 450 continue; 451 } 452 453 // Read ARP packet 454 if (safe_read(sock_fd, &p, sizeof(p)) < 0) { 455 bb_perror_msg_and_die(bb_msg_read_error); 456 } 457 458 if (p.eth.ether_type != htons(ETHERTYPE_ARP)) 459 continue; 460 if (p.arp.arp_op != htons(ARPOP_REQUEST) 461 && p.arp.arp_op != htons(ARPOP_REPLY) 462 ) { 463 continue; 464 } 480 465 #ifdef DEBUG 481 { 482 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; 483 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; 484 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; 485 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; 486 VDBG("%s recv arp type=%d, op=%d,\n", 487 argv_intf, ntohs(p.eth.ether_type), 488 ntohs(p.arp.arp_op)); 489 VDBG("\tsource=%s %s\n", 490 ether_ntoa(sha), 491 inet_ntoa(*spa)); 492 VDBG("\ttarget=%s %s\n", 493 ether_ntoa(tha), 494 inet_ntoa(*tpa)); 495 } 466 { 467 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; 468 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; 469 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; 470 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; 471 VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa)); 472 VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa)); 473 } 496 474 #endif 497 if (p.arp.arp_op != htons(ARPOP_REQUEST) 498 && p.arp.arp_op != htons(ARPOP_REPLY)) 499 continue; 500 501 source_ip_conflict = 0; 502 target_ip_conflict = 0; 503 504 if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 505 && memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0 506 ) { 507 source_ip_conflict = 1; 475 ip_conflict = 0; 476 if (memcmp(&p.arp.arp_sha, &G.our_ethaddr, ETH_ALEN) != 0) { 477 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) { 478 // A probe or reply with source_ip == chosen ip 479 ip_conflict = 1; 508 480 } 509 481 if (p.arp.arp_op == htons(ARPOP_REQUEST) 510 && memcmp(p.arp.arp_ tpa, &ip.s_addr, sizeof(struct in_addr)) == 0511 && memcmp( &p.arp.arp_tha, ð_addr, ETH_ALEN) != 0482 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0 483 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0 512 484 ) { 513 target_ip_conflict = 1; 485 // A probe with source_ip == 0.0.0.0, target_ip == chosen ip: 486 // another host trying to claim this ip! 487 ip_conflict |= 2; 514 488 } 515 516 VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", 517 state, source_ip_conflict, target_ip_conflict); 518 switch (state) { 519 case PROBE: 520 case ANNOUNCE: 521 // When probing or announcing, check for source IP conflicts 522 // and other hosts doing ARP probes (target IP conflicts). 523 if (source_ip_conflict || target_ip_conflict) { 524 conflicts++; 525 if (conflicts >= MAX_CONFLICTS) { 526 VDBG("%s ratelimit\n", argv_intf); 527 timeout_ms = RATE_LIMIT_INTERVAL * 1000; 528 state = RATE_LIMIT_PROBE; 529 } 530 531 // restart the whole protocol 532 ip.s_addr = pick(); 533 timeout_ms = 0; 534 nprobes = 0; 535 nclaims = 0; 536 } 537 break; 538 case MONITOR: 539 // If a conflict, we try to defend with a single ARP probe. 540 if (source_ip_conflict) { 541 VDBG("monitor conflict -- defending\n"); 542 state = DEFEND; 543 timeout_ms = DEFEND_INTERVAL * 1000; 544 arp(/* ARPOP_REQUEST, */ 545 /* ð_addr, */ ip, 546 ð_addr, ip); 547 } 548 break; 549 case DEFEND: 550 // Well, we tried. Start over (on conflict). 551 if (source_ip_conflict) { 552 state = PROBE; 553 VDBG("defend conflict -- starting over\n"); 554 ready = 0; 555 run(argv, "deconfig", &ip); 556 557 // restart the whole protocol 558 ip.s_addr = pick(); 559 timeout_ms = 0; 560 nprobes = 0; 561 nclaims = 0; 562 } 563 break; 564 default: 565 // Invalid, should never happen. Restart the whole protocol. 566 VDBG("invalid state -- starting over\n"); 567 state = PROBE; 568 ip.s_addr = pick(); 569 timeout_ms = 0; 570 nprobes = 0; 571 nclaims = 0; 572 break; 573 } // switch state 574 break; // case 1 (packets arriving) 575 } // switch poll 489 } 490 VDBG("state:%d ip_conflict:%d\n", state, ip_conflict); 491 if (!ip_conflict) 492 continue; 493 494 // Either src or target IP conflict exists 495 if (state <= ANNOUNCE) { 496 // PROBE or ANNOUNCE 497 conflicts++; 498 timeout_ms = PROBE_MIN * 1000 499 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts); 500 goto new_nip_and_PROBE; 501 } 502 503 // MONITOR or DEFEND: only src IP conflict is a problem 504 if (ip_conflict & 1) { 505 if (state == MONITOR) { 506 // Src IP conflict, defend with a single ARP probe 507 VDBG("monitor conflict - defending\n"); 508 timeout_ms = DEFEND_INTERVAL * 1000; 509 state = DEFEND; 510 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip); 511 continue; 512 } 513 // state == DEFEND 514 // Another src IP conflict, start over 515 VDBG("defend conflict - starting over\n"); 516 run(argv, "deconfig", chosen_nip); 517 conflicts = 0; 518 timeout_ms = 0; 519 goto new_nip_and_PROBE; 520 } 521 // Note: if we only have a target IP conflict here (ip_conflict & 2), 522 // IOW: if we just saw this sort of ARP packet: 523 // aa:bb:cc:dd:ee:ff > xx:xx:xx:xx:xx:xx arp who-has <chosen_nip> tell 0.0.0.0 524 // we expect _kernel_ to respond to that, because <chosen_nip> 525 // is (expected to be) configured on this iface. 576 526 } // while (1) 577 527 #undef argv_intf
Note:
See TracChangeset
for help on using the changeset viewer.