void rip_incoming(ssize_t n) /* Use a RIP packet to add to the router table. (RIP packets are really for * between routers, but often it is the only information around.) */ { udp_io_hdr_t *udp_io_hdr; u32_t default_dist; i32_t pref; routeinfo_t *routeinfo; struct routedata *data, *end; /* We don't care about RIP packets when there are router adverts. */ if (now + MaxAdvertisementInterval < router_advert_valid) return; udp_io_hdr= (udp_io_hdr_t *) rip_buf; if (udp_io_hdr->uih_data_len != n - sizeof(*udp_io_hdr)) { if (debug) printf("Bad sized route packet (discarded)\n"); return; } routeinfo= (routeinfo_t *) (rip_buf + sizeof(*udp_io_hdr) + udp_io_hdr->uih_ip_opt_len); if (routeinfo->command != RIP_REPLY) { if (debug) { printf("RIP-%d packet command %d ignored\n", routeinfo->version, routeinfo->command); } return; } /* Look for a default route, the route to the gateway. */ end= (struct routedata *) (rip_buf + n); default_dist= (u32_t) -1; for (data= routeinfo->data; data < end; data++) { if (ntohs(data->family) != AF_INET || data->ip_addr != 0) continue; default_dist= ntohl(data->metric); if (default_dist >= 256) { if (debug) { printf("Strange metric %lu\n", (unsigned long) default_dist); } } } pref= default_dist >= 256 ? 1 : 512 - default_dist; pref+= priority_offset; /* Add the gateway to the table with the calculated preference. */ add_gateway(udp_io_hdr->uih_src_addr, pref); if (debug) { printf("Routing table after RIP-%d packet from %s:\n", routeinfo->version, addr2name(udp_io_hdr->uih_src_addr)); print_table(); } /* Start advertizing. */ if (next_advert == NEVER) next_advert= IMMEDIATELY; }
void irdp_incoming(ssize_t n) /* Look for router solicitations and router advertisements. The solicitations * are probably from other irdpd daemons, we answer them if we do not expect * a real router to answer. The advertisements cause this daemon to shut up. */ { ip_hdr_t *ip_hdr; icmp_hdr_t *icmp_hdr; int ip_hdr_len; char *data; int i; int router; ipaddr_t addr; i32_t pref; time_t valid; ip_hdr= (ip_hdr_t *) irdp_buf; ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2; if (n < ip_hdr_len + 8) { if (debug) printf("Bad sized ICMP (discarded)\n"); return; } icmp_hdr= (icmp_hdr_t *)(irdp_buf + ip_hdr_len); /* Did I send this myself? */ if (ip_hdr->ih_src == ip_hdr->ih_dst) return; if ((htonl(ip_hdr->ih_src) & 0xFF000000L) == 0x7F000000L) return; if (icmp_hdr->ih_type != ICMP_TYPE_ROUTER_ADVER) return; /* Incoming router advertisement, the kind of packet the TCP/IP task * is very happy with. No need to solicit further. */ sol_retries= 0; /* Add router info to our table. Also see if the packet really came * from a router. If so then we can go dormant for the lifetime of * the ICMP. */ router= 0; data= (char *) icmp_hdr->ih_dun.uhd_data; for (i= 0; i < icmp_hdr->ih_hun.ihh_ram.iram_na; i++) { addr= * (ipaddr_t *) data; data+= sizeof(ipaddr_t); pref= htonl(* (i32_t *) data); data+= sizeof(i32_t); if (addr == ip_hdr->ih_src) { /* The sender is in the routing table! */ router= 1; } add_gateway(addr, pref); } valid= now + ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt); if (router) router_advert_valid= valid; /* Restart advertizing close to the timeout of the advert. (No more * irdpd adverts if the router stays alive.) */ if (router || next_advert > valid - DANGER) next_advert= valid - DANGER; if (debug) { printf("Routing table after advert received from %s:\n", addr2name(ip_hdr->ih_src)); print_table(); if (router) { struct tm *tm= localtime(&router_advert_valid); printf( "This router advert is valid until %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); } } }
static void read_ascii (FILE *fd, io_t *IO) { LINKED_LIST *ll_ann, *ll_with; bgp_attr_t *attr; int announce_flag = 0; int line_num = 0; int have_data = 0; int have_data2 = 0; time_t tstamp = 0; int type = 0; int subtype = 0; int bgptype = 0; int newtype = 0; gateway_t *gateway_from = NULL; gateway_t *gateway_to = NULL; int first = 1; u_char bgp_packet[BGPMAXPACKETSIZE], *bp = bgp_packet; u_char buffer[MAX_MSG_SIZE], *buffer_p = buffer; u_char *end = buffer + sizeof (buffer); int eof = 0; buffer_t *stdbuf; int state1 = 0, state2 = 0; int version = 0, as = 0, holdtime = 0, optlen = 0; u_long id = 0; int code = 0, subcode = 0; int viewno = 0; char *filename = NULL; prefix_t *route_prefix = NULL; time_t originated = 0; u_long status = 0; int seq_num = 0; attr = bgp_new_attr (PROTO_BGP); ll_ann = LL_Create (LL_DestroyFunction, Deref_Prefix, 0); ll_with = LL_Create (LL_DestroyFunction, Deref_Prefix, 0); stdbuf = New_Buffer_Stream (fd); for (;;) { char *line = NULL, *ret = NULL; int len = 0; int ok = 0; char *cp; if (buffer_gets (stdbuf) <= 0) { eof++; } else { len = buffer_data_len (stdbuf); line = buffer_data (stdbuf); if (line[len - 1] == '\n') { line[len - 1] = '\0'; len--; } trace (TR_TRACE, MRT->trace, "++%s\n", line); line_num++; if ((cp = strpbrk (line, "#!")) != NULL) { *cp = '\0'; len = cp - line; } if (first && nulline (line)) continue; first = 0; } if (eof || nulline (line)) { if (have_data && have_data2) { trace (TR_ERROR, MRT->trace, "Mixture of two formats\n"); goto error; } if (bgptype == BGP_UPDATE && have_data) { flushout (IO, tstamp, type, subtype, attr, ll_ann, ll_with, gateway_to); } else if (have_data2) { flushout2 (IO, tstamp, type, subtype, bgp_packet, bp - bgp_packet, gateway_from, gateway_to); } else if (bgptype == BGP_KEEPALIVE) { if (type == MSG_PROTOCOL_BGP4MP) { memset (bgp_packet, 0xff, BGP_HEADER_MARKER_LEN); BGP_PUT_HDRTYPE (bgptype, bgp_packet); bp = bgp_packet + BGP_HEADER_LEN; BGP_PUT_HDRLEN (bp - bgp_packet, bgp_packet); } else { bp = bgp_packet; } flushout2 (IO, tstamp, type, subtype, bgp_packet, bp - bgp_packet, gateway_from, gateway_to); } else if (bgptype == BGP_OPEN) { if (type == MSG_PROTOCOL_BGP4MP) { memset (bgp_packet, 0xff, BGP_HEADER_MARKER_LEN); BGP_PUT_HDRTYPE (bgptype, bgp_packet); bp = bgp_packet + BGP_HEADER_LEN; } else { bp = bgp_packet; } BGP_PUT_BYTE (version, bp); BGP_PUT_SHORT (as, bp); BGP_PUT_SHORT (holdtime, bp); BGP_PUT_NETLONG (id, bp); BGP_PUT_BYTE (0, bp); /* XXX */ if (type == MSG_PROTOCOL_BGP4MP) { BGP_PUT_HDRLEN (bp - bgp_packet, bgp_packet); } flushout2 (IO, tstamp, type, subtype, bgp_packet, bp - bgp_packet, gateway_from, gateway_to); } else if (bgptype == BGP_NOTIFY) { if (type == MSG_PROTOCOL_BGP4MP) { memset (bgp_packet, 0xff, BGP_HEADER_MARKER_LEN); BGP_PUT_HDRTYPE (bgptype, bgp_packet); bp = bgp_packet + BGP_HEADER_LEN; } else { bp = bgp_packet; } BGP_PUT_BYTE (code, bp); BGP_PUT_BYTE (subcode, bp); if (type == MSG_PROTOCOL_BGP4MP) { BGP_PUT_HDRLEN (bp - bgp_packet, bgp_packet); } flushout2 (IO, tstamp, type, subtype, bgp_packet, bp - bgp_packet, gateway_from, gateway_to); } else if (newtype == BGP4MP_STATE_CHANGE) { bp = bgp_packet; BGP_PUT_SHORT (state1, bp); BGP_PUT_SHORT (state2, bp); flushout2 (IO, tstamp, type, subtype, bgp_packet, bp - bgp_packet, gateway_from, NULL); } else if (newtype == BGP4MP_SNAPSHOT) { bp = bgp_packet; BGP_PUT_SHORT (viewno, bp); if (filename) BGP_PUT_DATA (filename, strlen (filename), bp); BGP_PUT_BYTE (0, bp); trace_mrt_header (MRT->trace, tstamp, type, subtype); io_write (IO, tstamp, type, subtype, bp - bgp_packet, bgp_packet); } else if (newtype == BGP4MP_ENTRY) { if (route_prefix != NULL) { buffer_p = bgp_table_dump_entry (buffer_p, end, type, subtype, viewno, route_prefix, status, originated, attr); } if (buffer_p - buffer > 0) { trace_mrt_header (MRT->trace, tstamp, type, subtype); io_write (IO, tstamp, type, subtype, buffer_p - buffer, buffer); } } if (eof) break; if (MRT->force_exit_flag) exit (1); bgp_deref_attr (attr); attr = bgp_new_attr (PROTO_BGP); LL_Clear (ll_ann); LL_Clear (ll_with); announce_flag = 0; have_data = 0; have_data2 = 0; tstamp = 0; type = 0; subtype = 0; bgptype = 0; newtype = 0; gateway_to = NULL; gateway_from = NULL; route_prefix = NULL; seq_num = 0; first = 1; if (filename) free (filename); filename = NULL; continue; } if (have_data) { /* a prefix -- line begins with a space */ if (isspace (line[0])) { prefix_t *prefix; char *cp = line +1; while (isspace (*cp)) cp++; if ((prefix = ascii2prefix (0, cp)) != NULL) { if (announce_flag == 1) { LL_Add (ll_ann, prefix); } else { LL_Add (ll_with, prefix); } continue; } } } if (have_data2) { prefix_t *prefix; int num; u_long value; if (isspace (line[0]) && strpbrk (line, ".:") && strchr (line, '/') && parse_line (line, "%d %m", &num, &prefix) == 2) { u_char *here = bp; /* v4 or v6 address with prefixlen */ #ifdef HAVE_IPV6 if (prefix->family == AF_INET6) BGP_PUT_PREFIX6 (prefix->bitlen, prefix_tochar (prefix), bp); else #endif /* HAVE_IPV6 */ BGP_PUT_PREFIX (prefix->bitlen, prefix_tochar (prefix), bp); Deref_Prefix (prefix); if (num != bp - here) { trace (TR_ERROR, MRT->trace, "length was %d but must be %d\n", num, bp - here); goto error; } continue; } else if (isspace (line[0]) && strpbrk (line, ".:") && parse_line (line, "%d %M", &num, &prefix) == 2) { /* v4 or v6 address w/o prefixlen */ if (prefix->family == AF_INET6 && num > 16) { trace (TR_ERROR, MRT->trace, "length was %d but must be less than or equal %d\n", num, 16); Deref_Prefix (prefix); goto error; } if (prefix->family == AF_INET && num > 4) { trace (TR_ERROR, MRT->trace, "length was %d but must be less than or equal %d\n", num, 4); Deref_Prefix (prefix); goto error; } BGP_PUT_DATA (prefix_tochar (prefix), num, bp); Deref_Prefix (prefix); continue; } else if (isspace (line[0]) && parse_line (line, "%d %i", &num, &value) == 2) { if (num == 1) BGP_PUT_BYTE (value, bp); else if (num == 2) BGP_PUT_SHORT (value, bp); else if (num == 4) BGP_PUT_LONG (value, bp); else { trace (TR_ERROR, MRT->trace, "unknown length %d\n", num); goto error; } continue; } } if ((ret = checkstradvance (line, "TIME"))) { struct tm tm; if (strptime (ret, "%D %T", &tm)) { time_t now; time (&now); tm.tm_isdst = localtime (&now)->tm_isdst; adjust_y2k (&tm); tstamp = mktime (&tm); } } else if ((ret = checkstradvance (line, "TO"))) { int as; char data[MAXLINE]; prefix_t *prefix; if (sscanf (ret, "%s AS%d", data, &as) >= 2 || sscanf (ret, "AS%d %s", &as, data) >= 2 /* obsolete */) { prefix = ascii2prefix (0, data); gateway_to = add_gateway (prefix, as, NULL); Deref_Prefix (prefix); } } else if ((ret = checkstradvance (line, "FROM"))) { int as; char data[MAXLINE]; if (sscanf (ret, "%s AS%d", data, &as) >= 2 || sscanf (ret, "AS%d %s", &as, data) >= 2 /* obsolete */) { prefix_t *prefix = ascii2prefix (0, data); gateway_from = add_gateway (prefix, as, NULL); attr->gateway = gateway_from; Deref_Prefix (prefix); } } /* type BGP/UPDATE */ else if ((ret = checkstradvance (line, "TYPE"))) { char *subtypestr; char **cpp; int i; if ((subtypestr = strchr (ret, '/')) != NULL) *subtypestr++ = '\0'; cpp = S_MRT_MSG_TYPES; for (i = 0; cpp[i]; i++) { if (strcasecmp (cpp[i], ret) == 0) break; } type = (enum MRT_MSG_TYPES) i; if (subtypestr) { char *subsubtypestr; if ((subsubtypestr = strchr (subtypestr, '/')) != NULL) *subsubtypestr++ = '\0'; if ((cpp = S_MRT_MSG_SUBTYPES[type]) != NULL) { for (i = 0; cpp[i]; i++) { if (strcasecmp (cpp[i], subtypestr) == 0) break; } subtype = i; } newtype = subtype; if (type == MSG_PROTOCOL_BGP || type == MSG_PROTOCOL_BGP4PLUS || type == MSG_PROTOCOL_BGP4PLUS_01) { if (subtype == MSG_BGP_UPDATE) { bgptype = BGP_UPDATE; newtype = BGP4MP_MESSAGE; } else if (subtype == MSG_BGP_KEEPALIVE) { bgptype = BGP_KEEPALIVE; newtype = BGP4MP_MESSAGE; } else if (subtype == MSG_BGP_NOTIFY) { bgptype = BGP_NOTIFY; newtype = BGP4MP_MESSAGE; } else if (subtype == MSG_BGP_OPEN) { bgptype = BGP_OPEN; newtype = BGP4MP_MESSAGE; } else if (subtype == MSG_BGP_SYNC) { newtype = BGP4MP_SNAPSHOT; } else if (subtype == MSG_BGP_STATE_CHANGE) { newtype = BGP4MP_STATE_CHANGE; } else if (subtype == MSG_TABLE_DUMP) { newtype = BGP4MP_ENTRY; } } else if (type == MSG_PROTOCOL_BGP4MP && ( subtype == BGP4MP_MESSAGE || subtype == BGP4MP_MESSAGE_OLD)) { for (i = 0; sbgp_pdus[i]; i++) { if (strcasecmp (sbgp_pdus[i], subsubtypestr) == 0) { bgptype = i; break; } } } } if (type == MSG_PROTOCOL_BGP || type == MSG_PROTOCOL_BGP4PLUS || type == MSG_PROTOCOL_BGP4PLUS_01 || type == MSG_TABLE_DUMP || type == MSG_PROTOCOL_BGP4MP ) { /* OK */ } else { trace (TR_ERROR, MRT->trace, "Unknown message type %s at line %d\n", ret, line_num); goto error; } } else if ((ret = checkstradvance (line, "DATA"))) { bp = bgp_packet; have_data2++; } else if (newtype == BGP4MP_STATE_CHANGE && (ret = checkstradvance (line, "PEER"))) { int as; char data[MAXLINE]; if (sscanf (ret, "%s AS%d", data, &as) >= 2 || sscanf (ret, "AS%d %s", &as, data) >= 2 /* obsolete */) { prefix_t *prefix = ascii2prefix (0, data); gateway_from = add_gateway (prefix, as, NULL); Deref_Prefix (prefix); } } else if (newtype == BGP4MP_STATE_CHANGE && (ret = checkstradvance (line, "STATE"))) { char *cp = strchr (ret, '/'); int i; if (cp == NULL) goto error; *cp++ = '\0'; for (i = 0; sbgp_states[i]; i++) { if (strcasecmp (sbgp_states[i], ret) == 0) { state1 = i; } } for (i = 0; sbgp_states[i]; i++) { if (strcasecmp (sbgp_states[i], cp) == 0) { state2 = i; } } } else if ((newtype == BGP4MP_SNAPSHOT || newtype == BGP4MP_ENTRY) && (ret = checkstradvance (line, "VIEW"))) { viewno = atoi (ret); } else if (newtype == BGP4MP_SNAPSHOT && (ret = checkstradvance (line, "FILE"))) { if (filename) free (filename); filename = strdup (ret); } else if (newtype == BGP4MP_ENTRY && (ret = checkstradvance (line, "PREFIX"))) { if (route_prefix == NULL) { buffer_p = buffer; if (type == MSG_TABLE_DUMP) { BGP_PUT_SHORT (viewno, buffer_p); BGP_PUT_SHORT (seq_num, buffer_p); } } else { buffer_p = bgp_table_dump_entry (buffer_p, end, type, subtype, viewno, route_prefix, status, originated, attr); } route_prefix = ascii2prefix (0, ret); bgp_deref_attr (attr); attr = bgp_new_attr (PROTO_BGP); } else if (newtype == BGP4MP_ENTRY && (ret = checkstradvance (line, "SEQUENCE"))) { seq_num = atoi (ret); } else if (newtype == BGP4MP_ENTRY && (ret = checkstradvance (line, "ORIGINATED"))) { struct tm tm; if (strptime (ret, "%D %T", &tm)) { time_t now; time (&now); tm.tm_isdst = localtime (&now)->tm_isdst; adjust_y2k (&tm); originated = mktime (&tm); } } else if (newtype == BGP4MP_ENTRY && (ret = checkstradvance (line, "STATUS"))) { sscanf (ret, "%li", &status); } else if (bgptype == BGP_OPEN && (ret = checkstradvance (line, "VERSION"))) { version = atoi (ret); } else if (bgptype == BGP_OPEN && (ret = checkstradvance (line, "AS"))) { as = atoi (ret); } else if (bgptype == BGP_OPEN && (ret = checkstradvance (line, "HOLD_TIME"))) { holdtime = atoi (ret); } else if (bgptype == BGP_OPEN && (ret = checkstradvance (line, "ID"))) { inet_pton (AF_INET, ret, &id); } else if (bgptype == BGP_OPEN && (ret = checkstradvance (line, "OPT_PARM_LEN"))) { optlen = atoi (ret); } else if (bgptype == BGP_NOTIFY && (ret = checkstradvance (line, "CODE"))) { char *cp; code = atoi (ret); if ((cp = strchr (ret, '/')) != NULL) subcode = atoi (cp + 1); } else if (bgptype == BGP_UPDATE && (ret = checkstradvance (line, "ANNOUNCE"))) { announce_flag = 1; have_data++; } else if (bgptype == BGP_UPDATE && (ret = checkstradvance (line, "WITHDRAW"))) { announce_flag = 0; have_data++; } else if ((bgptype == BGP_UPDATE || newtype == BGP4MP_ENTRY) && (ok = bgp_scan_attr (line, attr, MRT->trace)) > 0) { /* OK */ } else if ((bgptype == BGP_UPDATE || newtype == BGP4MP_ENTRY) && ok < 0) { trace (TR_ERROR, MRT->trace, "Invalid BGP attribute at line %d\n", line_num); goto error; } else { trace (TR_ERROR, MRT->trace, "Unrecognized line at %d\n", line_num); goto error; } } error: if (filename) free (filename); bgp_deref_attr (attr); LL_Destroy (ll_ann); LL_Destroy (ll_with); Delete_Buffer (stdbuf); }
int __connman_connection_gateway_add(struct connman_service *service, const char *gateway, enum connman_ipconfig_type type, const char *peer) { struct gateway_data *active_gateway = NULL; struct gateway_data *new_gateway = NULL; enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN, type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN; enum connman_service_type service_type = connman_service_get_type(service); int index; index = __connman_service_get_index(service); /* * If gateway is NULL, it's a point to point link and the default * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the * interface */ if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV4) gateway = "0.0.0.0"; if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6) gateway = "::"; DBG("service %p index %d gateway %s vpn ip %s type %d", service, index, gateway, peer, type); new_gateway = add_gateway(service, index, gateway, type); if (!new_gateway) return -EINVAL; active_gateway = find_active_gateway(); DBG("active %p index %d new %p", active_gateway, active_gateway ? active_gateway->index : -1, new_gateway); if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && new_gateway->ipv4_gateway) { add_host_route(AF_INET, index, gateway, service_type); __connman_service_nameserver_add_routes(service, new_gateway->ipv4_gateway->gateway); type4 = CONNMAN_IPCONFIG_TYPE_IPV4; } if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && new_gateway->ipv6_gateway) { add_host_route(AF_INET6, index, gateway, service_type); __connman_service_nameserver_add_routes(service, new_gateway->ipv6_gateway->gateway); type6 = CONNMAN_IPCONFIG_TYPE_IPV6; } if (service_type == CONNMAN_SERVICE_TYPE_VPN) { set_vpn_routes(new_gateway, service, gateway, type, peer, active_gateway); } else { if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && new_gateway->ipv4_gateway) new_gateway->ipv4_gateway->vpn = false; if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && new_gateway->ipv6_gateway) new_gateway->ipv6_gateway->vpn = false; } if (!active_gateway) { set_default_gateway(new_gateway, type); goto done; } if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && new_gateway->ipv4_gateway && new_gateway->ipv4_gateway->vpn) { if (!__connman_service_is_split_routing(new_gateway->service)) connman_inet_clear_gateway_address( active_gateway->index, active_gateway->ipv4_gateway->gateway); } if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && new_gateway->ipv6_gateway && new_gateway->ipv6_gateway->vpn) { if (!__connman_service_is_split_routing(new_gateway->service)) connman_inet_clear_ipv6_gateway_address( active_gateway->index, active_gateway->ipv6_gateway->gateway); } done: if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_READY, CONNMAN_IPCONFIG_TYPE_IPV4); if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_READY, CONNMAN_IPCONFIG_TYPE_IPV6); return 0; }