static int qif_set_qif (srsvp_t *srsvp, srsvp_interface_t *vif, int type) { u_char msgbuf[1024]; int ret; struct rt_msghdr *rtm = (struct rt_msghdr *) msgbuf; struct qos_msghdr *qosm = (struct qos_msghdr *) (rtm + 1); sockunion_t *su = (sockunion_t *) (qosm + 1); prefix_t *gateway; memset (rtm, 0, sizeof (*rtm)); memset (qosm, 0, sizeof (*qosm)); assert (type == RTM_QIF_ADD || type == RTM_QIF_DEL); rtm->rtm_type = type; rtm->rtm_msglen = sizeof (*rtm) + sizeof (*qosm); qosm->qifi = vif->interface->index; if (type == RTM_QIF_ADD) { qosm->flags = QOS_QIF_MULTI; qosm->queue_alg = (vif->qalg)? vif->qalg: ALTQ_PRQ; /* XXX */ qosm->qos.rdly = (vif->qlimit >= 0)? vif->qlimit: 200; /* XXX */ } gateway = vif->prefix; assert (gateway); #ifdef HAVE_IPV6 if (gateway->family == AF_INET6) { memset (su, 0, sizeof (su->sin6)); su->sin6.sin6_family = AF_INET6; su->sin6.sin6_len = sizeof (su->sin6); memcpy (&su->sin6.sin6_addr, prefix_tochar (gateway), 16); rtm->rtm_msglen += sizeof (su->sin6); } else #endif /* HAVE_IPV6 */ { memset (su, 0, sizeof (su->sin)); su->sin.sin_family = AF_INET; su->sin.sin_len = sizeof (su->sin); memcpy (&su->sin.sin_addr, prefix_tochar (gateway), 4); rtm->rtm_msglen += sizeof (su->sin); } if ((ret = qif_sendmsg (rtm)) < 0) { trace (TR_ERROR, MRT->trace, "QIF qif_set_qif (%m)\n"); } else { trace (TR_INFO, MRT->trace, "QIF %s:%d %s\n", vif->interface->name, vif->interface->index, (type == RTM_QIF_ADD)? "created": "removed"); } return (ret); }
int qif_notify (srsvp_t *srsvp, srsvp_flow_t *flow, int eno) { u_char msgbuf[1024]; int ret; struct rt_msghdr *rtm = (struct rt_msghdr *) msgbuf; struct qos_msghdr *qosm = (struct qos_msghdr *) (rtm + 1); qos_rtflow_t *qosr = (qos_rtflow_t *) (qosm + 1); memset (rtm, 0, sizeof (*rtm)); memset (qosm, 0, sizeof (*qosm)); rtm->rtm_type = RTM_FLOW_EXCEPT; rtm->rtm_msglen = sizeof (*rtm) + sizeof (*qosm); assert (flow); assert (flow->sender); assert (flow->destin); assert (flow->sender->family == flow->destin->family); #ifdef HAVE_IPV6 if (flow->upstream->prefix->family == AF_INET6) { memset (qosr, 0, sizeof (qosr->fin6)); qosr->fin6.family = AF_INET6; qosr->fin6.len = sizeof (qosr->fin6); qosr->fin6.proto = flow->proto; memcpy (&qosr->fin6.src, prefix_tochar (flow->sender), 16); memcpy (&qosr->fin6.dest, prefix_tochar (flow->destin), 16); qosr->fin6.sport = htons (flow->sport); qosr->fin6.dport = htons (flow->dport); rtm->rtm_msglen += sizeof (qosr->fin6); } else #endif /* HAVE_IPV6 */ { memset (qosr, 0, sizeof (qosr->fin)); qosr->fin.family = AF_INET; qosr->fin.len = sizeof (qosr->fin); qosr->fin.proto = flow->proto; memcpy (&qosr->fin.src, prefix_tochar (flow->sender), 4); memcpy (&qosr->fin.dest, prefix_tochar (flow->destin), 4); qosr->fin.sport = htons (flow->sport); qosr->fin.dport = htons (flow->dport); rtm->rtm_msglen += sizeof (qosr->fin); } if ((ret = qif_sendmsg (rtm)) < 0) { trace (TR_ERROR, MRT->trace, "QIF qif_notify (%m)\n"); } return (ret); }
/* * return 1 if permit, 0 if denied, -1 if not matched */ int apply_condition (condition_t *condition, prefix_t *prefix) { assert (condition); if (condition->prefix == NULL) /* all */ return (condition->permit); /* family the same */ if ((prefix->family == condition->prefix->family) && /* refine */ ((condition->refine && prefix->bitlen > condition->prefix->bitlen) || /* no refine or exact */ ((!condition->refine || condition->exact) && prefix->bitlen == condition->prefix->bitlen)) && /* prefix compare up to bitlen with wildcard */ byte_compare (prefix_tochar (prefix), prefix_tochar (condition->prefix), condition->prefix->bitlen, (condition->wildcard)? prefix_tochar (condition->wildcard): NULL)) return (condition->permit); return (-1); }
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); }
static int qif_set_flow (srsvp_t *srsvp, srsvp_flow_t *flow, srsvp_leaf_t *leaf, int type) { u_char msgbuf[1024]; int ret; struct rt_msghdr *rtm = (struct rt_msghdr *) msgbuf; struct qos_msghdr *qosm = (struct qos_msghdr *) (rtm + 1); qos_rtflow_t *qosr = (qos_rtflow_t *) (qosm + 1); sockunion_t *su; prefix_t *gateway; memset (rtm, 0, sizeof (*rtm)); memset (qosm, 0, sizeof (*qosm)); assert (type == RTM_FLOW_ADD || type == RTM_FLOW_DEL); rtm->rtm_type = type; rtm->rtm_msglen = sizeof (*rtm) + sizeof (*qosm); assert (flow); assert (leaf); qosm->qifi = leaf->neighbor->vif->interface->index; if (type == RTM_FLOW_ADD) { if (flow->upstream) qosm->parent = flow->upstream->vif->interface->index; else qosm->parent = qosm->qifi; /* XXX I'm not sure */ memcpy (&qosm->qos, leaf->req_qos, sizeof (qosm->qos)); qosm->flags = (QOS_FLOW_QOS | QOS_FLOW_ROUTE); } assert (flow->sender); assert (flow->destin); assert (flow->sender->family == flow->destin->family); #ifdef HAVE_IPV6 if (flow->upstream->prefix->family == AF_INET6) { memset (qosr, 0, sizeof (qosr->fin6)); qosr->fin6.family = AF_INET6; qosr->fin6.len = sizeof (qosr->fin6); qosr->fin6.proto = flow->proto; memcpy (&qosr->fin6.src, prefix_tochar (flow->sender), 16); memcpy (&qosr->fin6.dest, prefix_tochar (leaf->destin), 16); qosr->fin6.sport = htons (flow->sport); qosr->fin6.dport = htons (flow->dport); rtm->rtm_msglen += sizeof (qosr->fin6); su = (sockunion_t *)(((u_char *) qosr) + sizeof (qosr->fin6)); } else #endif /* HAVE_IPV6 */ { memset (qosr, 0, sizeof (qosr->fin)); qosr->fin.family = AF_INET; qosr->fin.len = sizeof (qosr->fin); qosr->fin.proto = flow->proto; memcpy (&qosr->fin.src, prefix_tochar (flow->sender), 4); memcpy (&qosr->fin.dest, prefix_tochar (flow->destin), 4); qosr->fin.sport = htons (flow->sport); qosr->fin.dport = htons (flow->dport); rtm->rtm_msglen += sizeof (qosr->fin); su = (sockunion_t *)(((u_char *) qosr) + sizeof (qosr->fin)); } gateway = leaf->neighbor->prefix; assert (gateway); #ifdef HAVE_IPV6 if (gateway->family == AF_INET6) { memset (su, 0, sizeof (su->sin6)); su->sin6.sin6_family = AF_INET6; su->sin6.sin6_len = sizeof (su->sin6); memcpy (&su->sin6.sin6_addr, prefix_tochar (gateway), 16); rtm->rtm_msglen += sizeof (su->sin6); } else #endif /* HAVE_IPV6 */ { memset (su, 0, sizeof (su->sin)); su->sin.sin_family = AF_INET; su->sin.sin_len = sizeof (su->sin); memcpy (&su->sin.sin_addr, prefix_tochar (gateway), 4); rtm->rtm_msglen += sizeof (su->sin); } qosm->flags |= QOS_FLOW_GATEWAY; if ((ret = qif_sendmsg (rtm)) < 0) { trace (TR_ERROR, MRT->trace, "QIF qif_set_flow (%m)\n"); } else { trace (TR_INFO, MRT->trace, "QIF flow %a port %d index %d %s\n", flow->destin, flow->dport, qosm->qifi, (type == RTM_FLOW_ADD)? "created": "removed"); } return (ret); }