| 3455 | } |
| 3456 | |
| 3457 | static void |
| 3458 | get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask) |
| 3459 | { |
| 3460 | int i; |
| 3461 | size_t l; |
| 3462 | char *ap, *ptr, *optr; |
| 3463 | struct ether_addr *mac; |
| 3464 | const char *macset = "0123456789abcdefABCDEF:"; |
| 3465 | |
| 3466 | if (strcmp(p, "any") == 0) { |
| 3467 | for (i = 0; i < ETHER_ADDR_LEN; i++) |
| 3468 | addr[i] = mask[i] = 0; |
| 3469 | return; |
| 3470 | } |
| 3471 | |
| 3472 | optr = ptr = strdup(p); |
| 3473 | if ((ap = strsep(&ptr, "&/")) != NULL && *ap != 0) { |
| 3474 | l = strlen(ap); |
| 3475 | if (strspn(ap, macset) != l || (mac = ether_aton(ap)) == NULL) |
| 3476 | errx(EX_DATAERR, "Incorrect MAC address"); |
| 3477 | bcopy(mac, addr, ETHER_ADDR_LEN); |
| 3478 | } else |
| 3479 | errx(EX_DATAERR, "Incorrect MAC address"); |
| 3480 | |
| 3481 | if (ptr != NULL) { /* we have mask? */ |
| 3482 | if (p[ptr - optr - 1] == '/') { /* mask len */ |
| 3483 | long ml = strtol(ptr, &ap, 10); |
| 3484 | if (*ap != 0 || ml > ETHER_ADDR_LEN * 8 || ml < 0) |
| 3485 | errx(EX_DATAERR, "Incorrect mask length"); |
| 3486 | for (i = 0; ml > 0 && i < ETHER_ADDR_LEN; ml -= 8, i++) |
| 3487 | mask[i] = (ml >= 8) ? 0xff: (~0) << (8 - ml); |
| 3488 | } else { /* mask */ |
| 3489 | l = strlen(ptr); |
| 3490 | if (strspn(ptr, macset) != l || |
| 3491 | (mac = ether_aton(ptr)) == NULL) |
| 3492 | errx(EX_DATAERR, "Incorrect mask"); |
| 3493 | bcopy(mac, mask, ETHER_ADDR_LEN); |
| 3494 | } |
| 3495 | } else { /* default mask: ff:ff:ff:ff:ff:ff */ |
| 3496 | for (i = 0; i < ETHER_ADDR_LEN; i++) |
| 3497 | mask[i] = 0xff; |
| 3498 | } |
| 3499 | for (i = 0; i < ETHER_ADDR_LEN; i++) |
| 3500 | addr[i] &= mask[i]; |
| 3501 | |
| 3502 | free(optr); |
| 3503 | } |
| 3504 | |
| 3505 | /* |
| 3506 | * helper function, updates the pointer to cmd with the length |