/* Send a single update or retraction. */ int send_update(int sock, struct interface *interface, int retract) { unsigned char buf[12 + 20]; int i = 0; if(!have_prefix) /* Nothing to announce. */ return 0; buf[i] = MESSAGE_ROUTER_ID; i++; /* Type */ buf[i] = 10; i++; /* Length */ DO_HTONS(buf + i, 0); i += 2; memcpy(buf + i, my_router_id, 8); i += 8; buf[i] = MESSAGE_UPDATE; i++; /* Type */ buf[i] = 18; i++; /* Length */ buf[i] = AE_IPV6; i++; /* AE */ buf[i] = 0; i++; /* Flags */ buf[i] = 64; i++; /* Plen */ buf[i] = 0; i++; /* Omitted */ DO_HTONS(buf + i, update_interval * 100); i+= 2; /* Interval */ DO_HTONS(buf + i, myseqno); i += 2; /* Seqno */ DO_HTONS(buf + i, retract ? INFINITY : 0); i += 2; /* Metric */ memcpy(buf + i, myprefix, 8); i += 8; /* Address */ assert(i == 12 + 20); return send_packet(sock, interface->ifindex, &babel_group, buf, i); }
int buffer_tlv(int type, const unsigned char *data, int datalen, const struct sockaddr_in6 *sin6, struct interface *interface) { if(interface && sin6) { errno = EINVAL; return -1; } if(sendbuf == NULL) sendbuf = allocate_buffer(SENDBUF_SIZE); if(sendbuf == NULL) return -1; if(buffered && ((interface && interface != buffered_interface) || (!interface && (buffered_interface || memcmp(sin6, &buffered_sin6, sizeof(*sin6)) != 0)) || buffered + datalen > 1400)) flushbuf(); if(buffered + datalen + 4 > SENDBUF_SIZE) { errno = EMSGSIZE; return -1; } if(!buffered) { /* NODE-ENDPOINT */ DO_HTONS(sendbuf + 0, 3); DO_HTONS(sendbuf + 2, 8); memcpy(sendbuf + 4, myid, 4); DO_HTONL(sendbuf + 8, interface ? interface->ifindex : sin6->sin6_scope_id); buffered = 12; } if(interface) buffered_interface = interface; else memcpy(&buffered_sin6, sin6, sizeof(*sin6)); DO_HTONS(sendbuf + buffered, type); buffered += 2; DO_HTONS(sendbuf + buffered, datalen); buffered += 2; memcpy(sendbuf + buffered, data, datalen); buffered += datalen; if(debug_level >= 3) debugf("Buffering %s %d (%d)\n", interface ? "multicast" : "unicast", type, datalen); return 1; }
static int dnsBuildQuery(int id, char *buf, int offset, int n, AtomPtr name, int af) { int i = offset; int type; switch(af) { case 4: type = 1; break; case 6: type = 28; break; default: return -EINVAL; } if(i + 12 >= n) return -1; DO_HTONS(&buf[i], id); i += 2; DO_HTONS(&buf[i], 1<<8); i += 2; DO_HTONS(&buf[i], 1); i += 2; DO_HTONS(&buf[i], 0); i += 2; DO_HTONS(&buf[i], 0); i += 2; DO_HTONS(&buf[i], 0); i += 2; i = stringToLabels(buf, i, n, name->string); if(i < 0) return -ENAMETOOLONG; if(i + 4 >= n) return -ENAMETOOLONG; DO_HTONS(&buf[i], type); i += 2; DO_HTONS(&buf[i], 1); i += 2; return i; }
int send_hello(int sock, struct interface *interface) { unsigned char buf[8 + 16 * MAXNEIGHBOURS]; int i = 0, j; struct timeval now; /* Hello */ buf[i] = MESSAGE_HELLO; i++; /* Type */ buf[i] = 6; i++; /* Length */ DO_HTONS(buf + i, 0); i += 2; DO_HTONS(buf + i, interface->seqno); i += 2; /* Seqno */ interface->seqno++; DO_HTONS(buf + i, hello_interval * 100); i += 2; /* Interval */ gettime(&now); for(j = 0; j < numneighbours; j++) { unsigned short cost; if(neighbours[j].interface != interface) continue; if(neighbour_expired(j, &now)) cost = INFINITY; else cost = link_cost; /* IHU */ buf[i] = MESSAGE_IHU; i++; /* Type */ buf[i] = 14; i++; /* Length */ buf[i] = AE_LL; i++; /* AE */ buf[i] = 0; i++; DO_HTONS(buf + i, cost); i += 2; /* rxcost */ DO_HTONS(buf + i, hello_interval * 100); i += 2; /* Interval */ memcpy(buf + i, ((unsigned char *)(&neighbours[j].address)) + 8, 8); i += 8; /* Address */ } assert((i - 8) % 16 == 0 && i - 8 <= 16 * numneighbours); return send_packet(sock, interface->ifindex, &babel_group, buf, i); }
int send_packet(int sock, int ifindex, struct in6_addr *to, unsigned char *body, unsigned char bodylen) { struct sockaddr_in6 sin6; unsigned char header[4]; header[0] = 42; header[1] = 2; DO_HTONS(header + 2, bodylen); /* Additional jitter never harms. */ nap(10); memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; memcpy(&sin6.sin6_addr, &babel_group, 16); sin6.sin6_port = htons(babel_port); sin6.sin6_scope_id = ifindex; return babel_send(sock, header, 4, body, bodylen, (struct sockaddr*)&sin6, sizeof(sin6)); }