* Handler for ARP packets: checks their sanity and then * 1. If the ARP is a request for our IP, respond with our MAC address * 2. If the ARP is a response from our server, record its MAC address * * It needs to replicate partially the behaviour of arpintr() and * in_arpinput(). * * Parameters: * pcb a pointer to the live debugnet PCB * mb a pointer to an mbuf * containing the packet rece
| 273 | * Assumes the calling function will take care of freeing the mbuf |
| 274 | */ |
| 275 | void |
| 276 | debugnet_handle_arp(struct debugnet_pcb *pcb, struct mbuf **mb) |
| 277 | { |
| 278 | char buf[INET_ADDRSTRLEN]; |
| 279 | struct in_addr isaddr, itaddr; |
| 280 | struct ether_addr dst; |
| 281 | struct mbuf *m; |
| 282 | struct arphdr *ah; |
| 283 | struct ifnet *ifp; |
| 284 | uint8_t *enaddr; |
| 285 | int req_len, op; |
| 286 | |
| 287 | m = *mb; |
| 288 | ifp = m->m_pkthdr.rcvif; |
| 289 | if (m->m_len < sizeof(struct arphdr)) { |
| 290 | m = m_pullup(m, sizeof(struct arphdr)); |
| 291 | *mb = m; |
| 292 | if (m == NULL) { |
| 293 | DNETDEBUG("runt packet: m_pullup failed\n"); |
| 294 | return; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | ah = mtod(m, struct arphdr *); |
| 299 | if (ntohs(ah->ar_hrd) != ARPHRD_ETHER) { |
| 300 | DNETDEBUG("unknown hardware address 0x%2D)\n", |
| 301 | (unsigned char *)&ah->ar_hrd, ""); |
| 302 | return; |
| 303 | } |
| 304 | if (ntohs(ah->ar_pro) != ETHERTYPE_IP) { |
| 305 | DNETDEBUG("drop ARP for unknown protocol %d\n", |
| 306 | ntohs(ah->ar_pro)); |
| 307 | return; |
| 308 | } |
| 309 | req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); |
| 310 | if (m->m_len < req_len) { |
| 311 | m = m_pullup(m, req_len); |
| 312 | *mb = m; |
| 313 | if (m == NULL) { |
| 314 | DNETDEBUG("runt packet: m_pullup failed\n"); |
| 315 | return; |
| 316 | } |
| 317 | } |
| 318 | ah = mtod(m, struct arphdr *); |
| 319 | |
| 320 | op = ntohs(ah->ar_op); |
| 321 | memcpy(&isaddr, ar_spa(ah), sizeof(isaddr)); |
| 322 | memcpy(&itaddr, ar_tpa(ah), sizeof(itaddr)); |
| 323 | enaddr = (uint8_t *)IF_LLADDR(ifp); |
| 324 | |
| 325 | if (memcmp(ar_sha(ah), enaddr, ifp->if_addrlen) == 0) { |
| 326 | DNETDEBUG("ignoring ARP from myself\n"); |
| 327 | return; |
| 328 | } |
| 329 | |
| 330 | if (isaddr.s_addr == pcb->dp_client) { |
| 331 | printf("%s: %*D is using my IP address %s!\n", __func__, |
| 332 | ifp->if_addrlen, (u_char *)ar_sha(ah), ":", |
no test coverage detected