Exemplo n.º 1
0
static void
local_notify_route_1(int s, struct babel_route *route, int kind)
{
    char buf[512];
    int rc;
    const char *dst_prefix = format_prefix(route->src->prefix,
                                           route->src->plen);
    const char *src_prefix = format_prefix(route->src->src_prefix,
                                           route->src->src_plen);

    rc = snprintf(buf, 512,
                  "%s route %s-%lx-%s prefix %s from %s installed %s "
                  "id %s metric %d refmetric %d via %s if %s\n",
                  local_kind(kind),
                  dst_prefix, (unsigned long)route->neigh, src_prefix,
                  dst_prefix, src_prefix,
                  route->installed ? "yes" : "no",
                  format_eui64(route->src->id),
                  route_metric(route), route->refmetric,
                  format_address(route->neigh->address),
                  route->neigh->ifp->name);

    if(rc < 0 || rc >= 512)
        goto fail;

    rc = write_timeout(s, buf, rc);
    if(rc < 0)
        goto fail;
    return;

 fail:
    shutdown(s, 1);
    return;
}
Exemplo n.º 2
0
void
local_notify_route(struct route *route, int kind)
{
    char buf[512];
    int rc;

    if(local_socket < 0)
        return;

    rc = snprintf(buf, 512,
                  "%s route %s-%lx prefix %s installed %s "
                  "id %s metric %d refmetric %d via %s if %s\n",
                  local_kind(kind),
                  format_prefix(route->src->prefix, route->src->plen),
                  (unsigned long)route->neigh,
                  format_prefix(route->src->prefix, route->src->plen),
                  route->installed ? "yes" : "no",
                  format_eui64(route->src->id),
                  route_metric(route), route->refmetric,
                  format_address(route->neigh->address),
                  route->neigh->network->ifname);
    
    if(rc < 0 || rc >= 512)
        goto fail;

    rc = write_timeout(local_socket, buf, rc);
    if(rc < 0)
        goto fail;
    return;

 fail:
    shutdown(local_socket, 1);
    return;
}
Exemplo n.º 3
0
void radio_hdlr(uint8_t evt, void *data)
{
	struct radio_packet *packet = data;

	if (evt != RADIO_EVT_RX_COMPLETED) {
		ERROR("Unexpected radio evt: %u", evt);
		return;
	}

	if (!packet->crcstatus) {
		DBG("ch %u bad crc", channels[idx]);
		goto recv;
	}

	/* Link Layer specification section 2.3, Core 4.1, page 2505
	 *
	 * The length is the 6 LSB, and the minimum allowed payload is 6 bytes.
	 */
	if ((packet->pdu[1] & 0x3F) < 6) {
		DBG("ch %u bad length", channels[idx]);
		goto recv;
	}

	DBG("ch %u (%s)", channels[idx], format_address(data + 2));

recv:
	radio_recv(channels[idx], ADV_CHANNEL_AA, ADV_CHANNEL_CRC);
}
Exemplo n.º 4
0
void
local_notify_neighbour(struct neighbour *neigh, int kind)
{
    char buf[512];
    int rc;
    
    if(local_socket < 0)
        return;

    rc = snprintf(buf, 512,
                  "%s neighbour %lx address %s "
                  "if %s reach %04x rxcost %d txcost %d cost %d\n",
                  local_kind(kind),
                  /* Neighbours never move around in memory , so we can use the
                     address as a unique identifier. */
                  (unsigned long int)neigh,
                  format_address(neigh->address),
                  neigh->network->ifname,
                  neigh->reach,
                  neighbour_rxcost(neigh),
                  neighbour_txcost(neigh),
                  neighbour_cost(neigh));

    if(rc < 0 || rc >= 512)
        goto fail;

    rc = write_timeout(local_socket, buf, rc);
    if(rc < 0)
        goto fail;
    return;

 fail:
    shutdown(local_socket, 1);
    return;
}
Exemplo n.º 5
0
void adv_report_cb(struct adv_report *report)
{
	DBG("adv type %02x, addr type %02x", report->type, report->addr.type);
	DBG("address %s, data %s", format_address(report->addr.addr),
					format_data(report->data, report->len));

	memcpy(&peer_addr, &report->addr, sizeof(bdaddr_t));

	ll_scan_stop();
	ll_conn_create(SCAN_INTERVAL, SCAN_WINDOW, &peer_addr, 1);

}
Exemplo n.º 6
0
static void
print_kernel_route(int add, struct kernel_route *route)
{
    char ifname[IFNAMSIZ];

    if(!if_indextoname(route->ifindex, ifname))
      memcpy(ifname,"unk",4);

    fprintf(stderr,
            "%s kernel route: dest: %s gw: %s metric: %d if: %s(%d) \n",
            add == RTM_ADD ? "Add" :
            add == RTM_DELETE ? "Delete" : "Change",
            format_prefix(route->prefix, route->plen),
            format_address(route->gw),
            route->metric,
            ifname, route->ifindex
            );
}
Exemplo n.º 7
0
static void
local_notify_neighbour_1(struct local_socket *s,
                         struct neighbour *neigh, int kind)
{
    char buf[512], rttbuf[64];
    int rc;

    rttbuf[0] = '\0';
    if(valid_rtt(neigh)) {
        rc = snprintf(rttbuf, 64, " rtt %s rttcost %d",
                      format_thousands(neigh->rtt), neighbour_rttcost(neigh));
        if(rc < 0 || rc >= 64)
            rttbuf[0] = '\0';
    }

    rc = snprintf(buf, 512,
                  "%s neighbour %lx address %s "
                  "if %s reach %04x rxcost %d txcost %d%s cost %d\n",
                  local_kind(kind),
                  /* Neighbours never move around in memory , so we can use the
                     address as a unique identifier. */
                  (unsigned long int)neigh,
                  format_address(neigh->address),
                  neigh->ifp->name,
                  neigh->reach,
                  neighbour_rxcost(neigh),
                  neighbour_txcost(neigh),
                  rttbuf,
                  neighbour_cost(neigh));

    if(rc < 0 || rc >= 512)
        goto fail;

    rc = write_timeout(s->fd, buf, rc);
    if(rc < 0)
        goto fail;
    return;

 fail:
    shutdown(s->fd, 1);
    return;
}
Exemplo n.º 8
0
static void
local_notify_interface_1(struct local_socket *s,
                         struct interface *ifp, int kind)
{
    char buf[512], v4[INET_ADDRSTRLEN];
    int rc;
    int up;

    up = if_up(ifp);
    if(up && ifp->ipv4)
        inet_ntop(AF_INET, ifp->ipv4, v4, INET_ADDRSTRLEN);
    else
        v4[0] = '\0';
    if(up)
        rc = snprintf(buf, 512,
                      "%s interface %s up true%s%s%s%s\n",
                      local_kind(kind), ifp->name,
                      ifp->ll ? " ipv6 " : "",
                      ifp->ll ? format_address(*ifp->ll) : "",
                      v4[0] ? " ipv4 " : "", v4);
    else
        rc = snprintf(buf, 512, "%s interface %s up false\n",
                      local_kind(kind), ifp->name);

    if(rc < 0 || rc >= 512)
        goto fail;

    rc = write_timeout(s->fd, buf, rc);
    if(rc < 0)
        goto fail;
    return;

 fail:
    shutdown(s->fd, 1);
    return;
}
Exemplo n.º 9
0
Datum
connection_limits(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	TupleDesc	   tupdesc;
	AttInMetadata   *attinmeta;

	/* init on the first call */
	if (SRF_IS_FIRSTCALL())
	{

		MemoryContext oldcontext;

		funcctx = SRF_FIRSTCALL_INIT();
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);

		reset_rules();
		check_all_rules();

		/* number of rules */
		funcctx->max_calls = rules->n_rules;

		/* Build a tuple descriptor for our result type */
		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context "
							"that cannot accept type record")));

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;
		funcctx->tuple_desc = tupdesc;

		/* switch back to the old context */
		MemoryContextSwitchTo(oldcontext);

	}

	/* init the context */
	funcctx = SRF_PERCALL_SETUP();

	/* check if we have more data */
	if (funcctx->max_calls > funcctx->call_cntr)
	{
		HeapTuple	   tuple;
		Datum		   result;
		Datum		   values[6];
		bool			nulls[6];

		rule_t * rule = &(rules->rules[funcctx->call_cntr]);

		memset(nulls, 0, sizeof(nulls));

		/* rule line */
		values[0] = UInt32GetDatum(rule->line);

		/* database */
		if (rule->fields & CHECK_DBNAME)
			values[1] = CStringGetTextDatum(rule->database);
		else
			nulls[1] = TRUE;

		/* username */
		if (rule->fields & CHECK_USER)
			values[2] = CStringGetTextDatum(rule->user);
		else
			nulls[2] = TRUE;

		/* hostname or IP address */
		if (rule->fields & CHECK_HOST)
			values[3] = CStringGetTextDatum(rule->hostname);
		else if (rule->fields & CHECK_IP)
		{
			char buffer[256];
			memset(buffer, 0, 256);
			format_address(buffer, 256, (struct sockaddr*)&rule->ip, (struct sockaddr*)&rule->mask);
			values[3] = CStringGetTextDatum(buffer);
		}
		else
			nulls[3] = TRUE;

		/* count and limit */
		values[4] = UInt32GetDatum(rule->count);
		values[5] = UInt32GetDatum(rule->limit);

		/* Build and return the tuple. */
		tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);

		/* make the tuple into a datum */
		result = HeapTupleGetDatum(tuple);

		/* Here we want to return another item: */
		SRF_RETURN_NEXT(funcctx, result);

	}
	else
	{
		/* lock ProcArray (serialize the processes) */
		LWLockRelease(ProcArrayLock);

		/* Here we are done returning items and just need to clean up: */
		SRF_RETURN_DONE(funcctx);
	}
}
Exemplo n.º 10
0
static void
babel_print_v2(const u_char *cp, u_int length) {
    u_int i;
    u_short bodylen;
    u_char v4_prefix[16] =
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
    u_char v6_prefix[16] = {0};

    TCHECK2(*cp, 4);
    if (length < 4)
        goto corrupt;
    bodylen = EXTRACT_16BITS(cp + 2);
    printf(" (%u)", bodylen);

    /* Process the TLVs in the body */
    i = 0;
    while(i < bodylen) {
        const u_char *message;
        u_char type, len;

        message = cp + 4 + i;
        TCHECK2(*message, 2);
        ICHECK(i, 2);
        type = message[0];
        len = message[1];

        TCHECK2(*message, 2 + len);
        ICHECK(i, 2 + len);

        switch(type) {
        case MESSAGE_PAD1: {
            if(!vflag)
                printf(" pad1");
            else
                printf("\n\tPad 1");
        }
            break;

        case MESSAGE_PADN: {
            if(!vflag)
                printf(" padN");
            else
                printf("\n\tPad %d", len + 2);
        }
            break;

        case MESSAGE_ACK_REQ: {
            u_short nonce, interval;
            if(!vflag)
                printf(" ack-req");
            else {
                printf("\n\tAcknowledgment Request ");
                if(len < 6) goto corrupt;
                nonce = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                printf("%04x %d", nonce, interval);
            }
        }
            break;

        case MESSAGE_ACK: {
            u_short nonce;
            if(!vflag)
                printf(" ack");
            else {
                printf("\n\tAcknowledgment ");
                if(len < 2) goto corrupt;
                nonce = EXTRACT_16BITS(message + 2);
                printf("%04x", nonce);
            }
        }
            break;

        case MESSAGE_HELLO:  {
            u_short seqno, interval;
            if(!vflag)
                printf(" hello");
            else {
                printf("\n\tHello ");
                if(len < 6) goto corrupt;
                seqno = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                printf("seqno %u interval %u", seqno, interval);
            }
        }
            break;

        case MESSAGE_IHU: {
            unsigned short txcost, interval;
            if(!vflag)
                printf(" ihu");
            else {
                u_char address[16];
                int rc;
                printf("\n\tIHU ");
                if(len < 6) goto corrupt;
                txcost = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                rc = network_address(message[2], message + 8, len - 6, address);
                if(rc < 0) { printf("[|babel]"); break; }
                printf("%s txcost %u interval %d",
                       format_address(address), txcost, interval);
            }
        }
            break;

        case MESSAGE_ROUTER_ID: {
            if(!vflag)
                printf(" router-id");
            else {
                printf("\n\tRouter Id");
                if(len < 10) goto corrupt;
                printf(" %s", format_id(message + 4));
            }
        }
            break;

        case MESSAGE_NH: {
            if(!vflag)
                printf(" nh");
            else {
                int rc;
                u_char nh[16];
                printf("\n\tNext Hop");
                if(len < 2) goto corrupt;
                rc = network_address(message[2], message + 4, len - 2, nh);
                if(rc < 0) goto corrupt;
                printf(" %s", format_address(nh));
            }
        }
            break;

        case MESSAGE_UPDATE: {
            if(!vflag) {
                printf(" update");
                if(len < 1)
                    printf("/truncated");
                else
                    printf("%s%s%s",
                           (message[3] & 0x80) ? "/prefix": "",
                           (message[3] & 0x40) ? "/id" : "",
                           (message[3] & 0x3f) ? "/unknown" : "");
            } else {
                u_short interval, seqno, metric;
                u_char plen;
                int rc;
                u_char prefix[16];
                printf("\n\tUpdate");
                if(len < 10) goto corrupt;
                plen = message[4] + (message[2] == 1 ? 96 : 0);
                rc = network_prefix(message[2], message[4], message[5],
                                    message + 12,
                                    message[2] == 1 ? v4_prefix : v6_prefix,
                                    len - 10, prefix);
                if(rc < 0) goto corrupt;
                interval = EXTRACT_16BITS(message + 6);
                seqno = EXTRACT_16BITS(message + 8);
                metric = EXTRACT_16BITS(message + 10);
                printf("%s%s%s %s metric %u seqno %u interval %u",
                       (message[3] & 0x80) ? "/prefix": "",
                       (message[3] & 0x40) ? "/id" : "",
                       (message[3] & 0x3f) ? "/unknown" : "",
                       format_prefix(prefix, plen),
                       metric, seqno, interval);
                if(message[3] & 0x80) {
                    if(message[2] == 1)
                        memcpy(v4_prefix, prefix, 16);
                    else
                        memcpy(v6_prefix, prefix, 16);
                }
            }
        }
            break;

        case MESSAGE_REQUEST: {
            if(!vflag)
                printf(" request");
            else {
                int rc;
                u_char prefix[16], plen;
                printf("\n\tRequest ");
                if(len < 2) goto corrupt;
                plen = message[3] + (message[2] == 1 ? 96 : 0);
                rc = network_prefix(message[2], message[3], 0,
                                    message + 4, NULL, len - 2, prefix);
                if(rc < 0) goto corrupt;
                plen = message[3] + (message[2] == 1 ? 96 : 0);
                printf("for %s",
                       message[2] == 0 ? "any" : format_prefix(prefix, plen));
            }
        }
            break;

        case MESSAGE_MH_REQUEST : {
            if(!vflag)
                printf(" mh-request");
            else {
                int rc;
                u_short seqno;
                u_char prefix[16], plen;
                printf("\n\tMH-Request ");
                if(len < 14) goto corrupt;
                seqno = EXTRACT_16BITS(message + 4);
                rc = network_prefix(message[2], message[3], 0,
                                    message + 16, NULL, len - 14, prefix);
                if(rc < 0) goto corrupt;
                plen = message[3] + (message[2] == 1 ? 96 : 0);
                printf("(%u hops) for %s seqno %u id %s",
                       message[6], format_prefix(prefix, plen),
                       seqno, format_id(message + 8));
            }
        }
            break;
        default:
            if(!vflag)
                printf(" unknown");
            else
                printf("\n\tUnknown message type %d", type);
        }
        i += len + 2;
    }
    return;

 trunc:
    printf(" [|babel]");
    return;

 corrupt:
    printf(" (corrupt)");
    return;
}
Exemplo n.º 11
0
void rtsp_listen_loop(void) {
    struct addrinfo hints, *info, *p;
    char portstr[6];
    int *sockfd = NULL;
    int nsock = 0;
    int i, ret;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    snprintf(portstr, 6, "%d", config.port);

    ret = getaddrinfo(NULL, portstr, &hints, &info);
    if (ret) {
        die("getaddrinfo failed: %s", gai_strerror(ret));
    }

    for (p=info; p; p=p->ai_next) {
        int fd = socket(p->ai_family, p->ai_socktype, IPPROTO_TCP);
        int yes = 1;

        ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

#ifdef IPV6_V6ONLY
        // some systems don't support v4 access on v6 sockets, but some do.
        // since we need to account for two sockets we might as well
        // always.
        if (p->ai_family == AF_INET6)
            ret |= setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
#endif

        if (!ret)
            ret = bind(fd, p->ai_addr, p->ai_addrlen);

        // one of the address families will fail on some systems that
        // report its availability. do not complain.
        if (ret) {
            debug(1, "Failed to bind to address %s\n", format_address(p->ai_addr));
            continue;
        }
        debug(1, "Bound to address %s\n", format_address(p->ai_addr));

        listen(fd, 5);
        nsock++;
        sockfd = realloc(sockfd, nsock*sizeof(int));
        sockfd[nsock-1] = fd;
    }

    freeaddrinfo(info);

    if (!nsock)
        die("could not bind any listen sockets!");


    int maxfd = -1;
    fd_set fds;
    FD_ZERO(&fds);
    for (i=0; i<nsock; i++) {
        if (sockfd[i] > maxfd)
            maxfd = sockfd[i];
    }

    mdns_register();

    printf("Listening for connections.\n");
    shairport_startup_complete();

    int acceptfd;
    struct timeval tv;
    while (1) {
        tv.tv_sec = 300;
        tv.tv_usec = 0;

        for (i=0; i<nsock; i++)
            FD_SET(sockfd[i], &fds);

        ret = select(maxfd+1, &fds, 0, 0, &tv);
        if (ret<0) {
            if (errno==EINTR)
                continue;
            break;
        }

        cleanup_threads();

        acceptfd = -1;
        for (i=0; i<nsock; i++) {
            if (FD_ISSET(sockfd[i], &fds)) {
                acceptfd = sockfd[i];
                break;
            }
        }
        if (acceptfd < 0) // timeout
            continue;

        rtsp_conn_info *conn = malloc(sizeof(rtsp_conn_info));
        memset(conn, 0, sizeof(rtsp_conn_info));
        socklen_t slen = sizeof(conn->remote);

        debug(1, "new RTSP connection\n");
        conn->fd = accept(acceptfd, (struct sockaddr *)&conn->remote, &slen);
        if (conn->fd < 0) {
            perror("failed to accept connection");
            free(conn);
        } else {
            pthread_t rtsp_conversation_thread;
            ret = pthread_create(&rtsp_conversation_thread, NULL, rtsp_conversation_thread_func, conn);
            if (ret)
                die("Failed to create RTSP receiver thread!");

            conn->thread = rtsp_conversation_thread;
            conn->running = 1;
            track_thread(conn);
        }
    }
    perror("select");
    die("fell out of the RTSP select loop");
}
Exemplo n.º 12
0
static const char *
format_prefix(const unsigned char *prefix, unsigned char plen)
{
    return wmem_strdup_printf(wmem_packet_scope(), "%s/%u", format_address(prefix), plen);
}
Exemplo n.º 13
0
static int
dissect_babel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    unsigned char v4_prefix[16] = {0}, v6_prefix[16] = {0};
    int i = 0;
    proto_tree *babel_tree = NULL;
    guint8 version;
    guint16 bodylen;

    if(tvb_length(tvb) < 4)
        return 0;

    if(tvb_get_guint8(tvb, 0) != 42)
        return 0;
    version = tvb_get_guint8(tvb, 1);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Babel");
    col_set_str(pinfo->cinfo, COL_INFO, "Babel");

    if(version != 2) {
        col_add_fstr(pinfo->cinfo, COL_INFO, "Version %u", version);
        return 2;
    }

    if(tree) {
        ti = proto_tree_add_item(tree, proto_babel, tvb, 0, -1, ENC_NA);
        babel_tree = proto_item_add_subtree(ti, ett_babel);

        proto_tree_add_item(babel_tree, hf_babel_magic, tvb, 0, 1, ENC_NA);
        proto_tree_add_item(babel_tree, hf_babel_version, tvb, 1, 1, ENC_NA);
        proto_tree_add_item(babel_tree, hf_babel_bodylen,
                            tvb, 2, 2, ENC_BIG_ENDIAN);
    }

    bodylen = tvb_get_ntohs(tvb, 2);

    i = 0;
    while(i < bodylen) {
        guint8 type, len = 0, total_length;
        proto_tree *message_tree = NULL;
        int message = 4 + i;

        type = tvb_get_guint8(tvb, message);
        if(type == MESSAGE_PAD1)
            total_length = 1;
        else {
            len = tvb_get_guint8(tvb, message + 1);
            total_length = len + 2;
        }

        col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
                        val_to_str(type, messages, "unknown"));

        ti = proto_tree_add_uint_format(babel_tree, hf_babel_message,
                                        tvb, message, total_length, type,
                                        "Message %s (%u)",
                                        val_to_str(type, messages,
                                                "unknown"),
                                        type);

        if(tree) {
            message_tree = proto_item_add_subtree(ti, ett_message);
            proto_tree_add_item(message_tree, hf_babel_message_type,
                                tvb, message, 1, ENC_NA);
        }

        if(type == MESSAGE_PAD1) {
            i++;
            continue;
        }

        if(tree) {
            proto_tree_add_item(message_tree, hf_babel_message_length,
                                tvb, message + 1, 1, ENC_BIG_ENDIAN);

            if(type == MESSAGE_PADN) {
            } else if(type == MESSAGE_ACK_REQ) {
                proto_tree_add_item(message_tree, hf_babel_message_nonce,
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_interval,
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
            } else if(type == MESSAGE_ACK) {
                proto_tree_add_item(message_tree, hf_babel_message_nonce,
                                    tvb, message + 2, 2, ENC_BIG_ENDIAN);
            } else if(type == MESSAGE_HELLO) {
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_interval,
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
            } else if(type == MESSAGE_IHU) {
                proto_tree *subtree;
                unsigned char address[16];
                int rc =
                    network_address(tvb_get_guint8(tvb, message + 2),
                                    tvb_get_ptr(tvb, message + 8, len - 6),
                                    len - 6,
                                    address);
                proto_tree_add_item(message_tree, hf_babel_message_rxcost,
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_interval,
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
                ti = proto_tree_add_text(message_tree,
                                         tvb, message + 4, len - 2,
                                         "Address: %s",
                                         format_address(rc < 0 ?
                                                        NULL : address));
                subtree = proto_item_add_subtree(ti, ett_subtree);
                proto_tree_add_item(subtree, hf_babel_message_ae,
                                    tvb, message + 2, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_prefix,
                                    tvb, message + 4, len - 2, ENC_NA);
            } else if(type == MESSAGE_ROUTER_ID) {
                proto_tree_add_item(message_tree, hf_babel_message_routerid,
                                    tvb, message + 4, 8, ENC_NA);
            } else if(type == MESSAGE_NH) {
                proto_tree *subtree;
                unsigned char nh[16];
                int rc =
                    network_address(tvb_get_guint8(tvb, message + 2),
                                    tvb_get_ptr(tvb, message + 4, len - 2),
                                    len - 2,
                                    nh);
                ti = proto_tree_add_text(message_tree,
                                         tvb, message + 4, len - 2,
                                         "NH: %s",
                                         format_address(rc < 0 ? NULL : nh));
                subtree = proto_item_add_subtree(ti, ett_subtree);
                proto_tree_add_item(subtree, hf_babel_message_ae,
                                    tvb, message + 2, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_prefix,
                                    tvb, message + 4, len - 2, ENC_NA);
            } else if(type == MESSAGE_UPDATE) {
                proto_tree *subtree;
                unsigned char p[16];
                guint8 ae = tvb_get_guint8(tvb, message + 2);
                guint8 flags = tvb_get_guint8(tvb, message + 3);
                guint8 plen = tvb_get_guint8(tvb, message + 4);
                int rc =
                    network_prefix(ae, plen,
                                   tvb_get_guint8(tvb, message + 5),
                                   tvb_get_ptr(tvb, message + 12, len - 10),
                                   ae == 1 ? v4_prefix : v6_prefix,
                                   len - 10, p);
                if(rc >= 0 && (flags & 0x80)) {
                    if(ae == 1)
                        memcpy(v4_prefix, p, 16);
                    else
                        memcpy(v6_prefix, p, 16);
                }

                proto_tree_add_item(message_tree, hf_babel_message_flags,
                                    tvb, message + 3, 1, ENC_NA);
                proto_tree_add_item(message_tree, hf_babel_message_interval,
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
                                    tvb, message + 8, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_metric,
                                    tvb, message + 10, 2, ENC_BIG_ENDIAN);
                ti = proto_tree_add_text(message_tree,
                                         tvb, message + 12, len - 10,
                                         "Prefix: %s",
                                         format_prefix(rc < 0 ? NULL : p,
                                                       plen));
                subtree = proto_item_add_subtree(ti, ett_subtree);
                proto_tree_add_item(subtree, hf_babel_message_ae,
                                    tvb, message + 2, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_plen,
                                    tvb, message + 4, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_omitted,
                                    tvb, message + 5, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_prefix,
                                    tvb, message + 12, len - 10, ENC_NA);
            } else if(type == MESSAGE_REQUEST) {
                proto_tree *subtree;
                unsigned char p[16];
                guint8 plen = tvb_get_guint8(tvb, message + 3);
                int rc =
                    network_prefix(tvb_get_guint8(tvb, message + 2), plen,
                                   0,
                                   tvb_get_ptr(tvb, message + 4, len - 2),
                                   NULL,
                                   len - 2, p);
                ti = proto_tree_add_text(message_tree,
                                         tvb, message + 4, len - 2,
                                         "Prefix: %s",
                                         format_prefix(rc < 0 ? NULL : p,
                                                       plen));
                subtree = proto_item_add_subtree(ti, ett_subtree);
                proto_tree_add_item(subtree, hf_babel_message_ae,
                                    tvb, message + 2, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_plen,
                                    tvb, message + 3, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_prefix,
                                    tvb, message + 4, len - 2, ENC_NA);
            } else if(type == MESSAGE_MH_REQUEST) {
                proto_tree *subtree;
                unsigned char p[16];
                guint8 plen = tvb_get_guint8(tvb, message + 3);
                int rc =
                    network_prefix(tvb_get_guint8(tvb, message + 2), plen,
                                   0,
                                   tvb_get_ptr(tvb, message + 16, len - 14),
                                   NULL,
                                   len - 14, p);
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(message_tree, hf_babel_message_hopcount,
                                    tvb, message + 6, 1, ENC_NA);
                proto_tree_add_item(message_tree, hf_babel_message_routerid,
                                    tvb, message + 8, 8, ENC_NA);
                ti = proto_tree_add_text(message_tree,
                                         tvb, message + 16, len - 14,
                                         "Prefix: %s",
                                         format_prefix(rc < 0 ? NULL : p,
                                                       plen));
                subtree = proto_item_add_subtree(ti, ett_subtree);
                proto_tree_add_item(subtree, hf_babel_message_ae,
                                    tvb, message + 2, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_plen,
                                    tvb, message + 3, 1, ENC_NA);
                proto_tree_add_item(subtree, hf_babel_message_prefix,
                                    tvb, message + 16, len - 14, ENC_NA);
            }
        }
        i += len + 2;
    }
    return i;
}
Exemplo n.º 14
0
const char *
format_prefix(const unsigned char *prefix, unsigned char plen)
{
    return ep_strdup_printf("%s/%u", format_address(prefix), plen);
}
Exemplo n.º 15
0
static void
babel_print_v2(netdissect_options *ndo,
               const u_char *cp, u_int length)
{
    u_int i;
    u_short bodylen;
    u_char v4_prefix[16] =
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
    u_char v6_prefix[16] = {0};

    ND_TCHECK2(*cp, 4);
    if (length < 4)
        goto corrupt;
    bodylen = EXTRACT_16BITS(cp + 2);
    ND_PRINT((ndo, " (%u)", bodylen));

    /* Process the TLVs in the body */
    i = 0;
    while(i < bodylen) {
        const u_char *message;
        u_int type, len;

        message = cp + 4 + i;

        ND_TCHECK2(*message, 1);
        if((type = message[0]) == MESSAGE_PAD1) {
            ND_PRINT((ndo, ndo->ndo_vflag ? "\n\tPad 1" : " pad1"));
            i += 1;
            continue;
        }

        ND_TCHECK2(*message, 2);
        ICHECK(i, 2);
        len = message[1];

        ND_TCHECK2(*message, 2 + len);
        ICHECK(i, 2 + len);

        switch(type) {
        case MESSAGE_PADN: {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " padN"));
            else
                ND_PRINT((ndo, "\n\tPad %d", len + 2));
        }
            break;

        case MESSAGE_ACK_REQ: {
            u_short nonce, interval;
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " ack-req"));
            else {
                ND_PRINT((ndo, "\n\tAcknowledgment Request "));
                if(len < 6) goto corrupt;
                nonce = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                ND_PRINT((ndo, "%04x %s", nonce, format_interval(interval)));
            }
        }
            break;

        case MESSAGE_ACK: {
            u_short nonce;
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " ack"));
            else {
                ND_PRINT((ndo, "\n\tAcknowledgment "));
                if(len < 2) goto corrupt;
                nonce = EXTRACT_16BITS(message + 2);
                ND_PRINT((ndo, "%04x", nonce));
            }
        }
            break;

        case MESSAGE_HELLO:  {
            u_short seqno, interval;
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " hello"));
            else {
                ND_PRINT((ndo, "\n\tHello "));
                if(len < 6) goto corrupt;
                seqno = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                ND_PRINT((ndo, "seqno %u interval %s", seqno, format_interval(interval)));
                /* Extra data. */
                if(len > 6)
                    subtlvs_print(ndo, message + 8, message + 2 + len, type);
            }
        }
            break;

        case MESSAGE_IHU: {
            unsigned short txcost, interval;
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " ihu"));
            else {
                u_char address[16];
                int rc;
                ND_PRINT((ndo, "\n\tIHU "));
                if(len < 6) goto corrupt;
                txcost = EXTRACT_16BITS(message + 4);
                interval = EXTRACT_16BITS(message + 6);
                rc = network_address(message[2], message + 8, len - 6, address);
                if(rc < 0) { ND_PRINT((ndo, "%s", tstr)); break; }
                ND_PRINT((ndo, "%s txcost %u interval %s",
                       format_address(ndo, address), txcost, format_interval(interval)));
                /* Extra data. */
                if((u_int)rc < len - 6)
                    subtlvs_print(ndo, message + 8 + rc, message + 2 + len,
                                  type);
            }
        }
            break;

        case MESSAGE_ROUTER_ID: {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " router-id"));
            else {
                ND_PRINT((ndo, "\n\tRouter Id"));
                if(len < 10) goto corrupt;
                ND_PRINT((ndo, " %s", format_id(message + 4)));
            }
        }
            break;

        case MESSAGE_NH: {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " nh"));
            else {
                int rc;
                u_char nh[16];
                ND_PRINT((ndo, "\n\tNext Hop"));
                if(len < 2) goto corrupt;
                rc = network_address(message[2], message + 4, len - 2, nh);
                if(rc < 0) goto corrupt;
                ND_PRINT((ndo, " %s", format_address(ndo, nh)));
            }
        }
            break;

        case MESSAGE_UPDATE: {
            if (!ndo->ndo_vflag) {
                ND_PRINT((ndo, " update"));
                if(len < 1)
                    ND_PRINT((ndo, "/truncated"));
                else
                    ND_PRINT((ndo, "%s%s%s",
                           (message[3] & 0x80) ? "/prefix": "",
                           (message[3] & 0x40) ? "/id" : "",
                           (message[3] & 0x3f) ? "/unknown" : ""));
            } else {
                u_short interval, seqno, metric;
                u_char plen;
                int rc;
                u_char prefix[16];
                ND_PRINT((ndo, "\n\tUpdate"));
                if(len < 10) goto corrupt;
                plen = message[4] + (message[2] == 1 ? 96 : 0);
                rc = network_prefix(message[2], message[4], message[5],
                                    message + 12,
                                    message[2] == 1 ? v4_prefix : v6_prefix,
                                    len - 10, prefix);
                if(rc < 0) goto corrupt;
                interval = EXTRACT_16BITS(message + 6);
                seqno = EXTRACT_16BITS(message + 8);
                metric = EXTRACT_16BITS(message + 10);
                ND_PRINT((ndo, "%s%s%s %s metric %u seqno %u interval %s",
                       (message[3] & 0x80) ? "/prefix": "",
                       (message[3] & 0x40) ? "/id" : "",
                       (message[3] & 0x3f) ? "/unknown" : "",
                       format_prefix(ndo, prefix, plen),
                       metric, seqno, format_interval_update(interval)));
                if(message[3] & 0x80) {
                    if(message[2] == 1)
                        memcpy(v4_prefix, prefix, 16);
                    else
                        memcpy(v6_prefix, prefix, 16);
                }
                /* extra data? */
                if((u_int)rc < len - 10)
                    subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type);
            }
        }
            break;

        case MESSAGE_REQUEST: {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " request"));
            else {
                int rc;
                u_char prefix[16], plen;
                ND_PRINT((ndo, "\n\tRequest "));
                if(len < 2) goto corrupt;
                plen = message[3] + (message[2] == 1 ? 96 : 0);
                rc = network_prefix(message[2], message[3], 0,
                                    message + 4, NULL, len - 2, prefix);
                if(rc < 0) goto corrupt;
                ND_PRINT((ndo, "for %s",
                       message[2] == 0 ? "any" : format_prefix(ndo, prefix, plen)));
            }
        }
            break;

        case MESSAGE_MH_REQUEST : {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " mh-request"));
            else {
                int rc;
                u_short seqno;
                u_char prefix[16], plen;
                ND_PRINT((ndo, "\n\tMH-Request "));
                if(len < 14) goto corrupt;
                seqno = EXTRACT_16BITS(message + 4);
                rc = network_prefix(message[2], message[3], 0,
                                    message + 16, NULL, len - 14, prefix);
                if(rc < 0) goto corrupt;
                plen = message[3] + (message[2] == 1 ? 96 : 0);
                ND_PRINT((ndo, "(%u hops) for %s seqno %u id %s",
                       message[6], format_prefix(ndo, prefix, plen),
                       seqno, format_id(message + 8)));
            }
        }
            break;
        case MESSAGE_TSPC :
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " tspc"));
            else {
                ND_PRINT((ndo, "\n\tTS/PC "));
                if(len < 6) goto corrupt;
                ND_PRINT((ndo, "timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
                       EXTRACT_16BITS(message + 2)));
            }
            break;
        case MESSAGE_HMAC : {
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " hmac"));
            else {
                unsigned j;
                ND_PRINT((ndo, "\n\tHMAC "));
                if(len < 18) goto corrupt;
                ND_PRINT((ndo, "key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2));
                for (j = 0; j < len - 2; j++)
                    ND_PRINT((ndo, "%02X", message[4 + j]));
            }
        }
            break;

        case MESSAGE_UPDATE_SRC_SPECIFIC : {
            if(!ndo->ndo_vflag) {
                ND_PRINT((ndo, " ss-update"));
            } else {
                u_char prefix[16], src_prefix[16];
                u_short interval, seqno, metric;
                u_char ae, plen, src_plen, omitted;
                int rc;
                int parsed_len = 10;
                ND_PRINT((ndo, "\n\tSS-Update"));
                if(len < 10) goto corrupt;
                ae = message[2];
                src_plen = message[3];
                plen = message[4];
                omitted = message[5];
                interval = EXTRACT_16BITS(message + 6);
                seqno = EXTRACT_16BITS(message + 8);
                metric = EXTRACT_16BITS(message + 10);
                rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len,
                                    ae == 1 ? v4_prefix : v6_prefix,
                                    len - parsed_len, prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    plen += 96;
                parsed_len += rc;
                rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
                                    NULL, len - parsed_len, src_prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    src_plen += 96;
                parsed_len += rc;

                ND_PRINT((ndo, " %s from", format_prefix(ndo, prefix, plen)));
                ND_PRINT((ndo, " %s metric %u seqno %u interval %s",
                          format_prefix(ndo, src_prefix, src_plen),
                          metric, seqno, format_interval_update(interval)));
                /* extra data? */
                if((u_int)parsed_len < len)
                    subtlvs_print(ndo, message + 2 + parsed_len,
                                  message + 2 + len, type);
            }
        }
            break;

        case MESSAGE_REQUEST_SRC_SPECIFIC : {
            if(!ndo->ndo_vflag)
                ND_PRINT((ndo, " ss-request"));
            else {
                int rc, parsed_len = 3;
                u_char ae, plen, src_plen, prefix[16], src_prefix[16];
                ND_PRINT((ndo, "\n\tSS-Request "));
                if(len < 3) goto corrupt;
                ae = message[2];
                plen = message[3];
                src_plen = message[4];
                rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
                                    NULL, len - parsed_len, prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    plen += 96;
                parsed_len += rc;
                rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
                                    NULL, len - parsed_len, src_prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    src_plen += 96;
                parsed_len += rc;
                if(ae == 0) {
                    ND_PRINT((ndo, "for any"));
                } else {
                    ND_PRINT((ndo, "for (%s, ", format_prefix(ndo, prefix, plen)));
                    ND_PRINT((ndo, "%s)", format_prefix(ndo, src_prefix, src_plen)));
                }
            }
        }
            break;

        case MESSAGE_MH_REQUEST_SRC_SPECIFIC : {
            if(!ndo->ndo_vflag)
                ND_PRINT((ndo, " ss-mh-request"));
            else {
                int rc, parsed_len = 14;
                u_short seqno;
                u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc;
                const u_char *router_id = NULL;
                ND_PRINT((ndo, "\n\tSS-MH-Request "));
                if(len < 14) goto corrupt;
                ae = message[2];
                plen = message[3];
                seqno = EXTRACT_16BITS(message + 4);
                hopc = message[6];
                src_plen = message[7];
                router_id = message + 8;
                rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
                                    NULL, len - parsed_len, prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    plen += 96;
                parsed_len += rc;
                rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
                                    NULL, len - parsed_len, src_prefix);
                if(rc < 0) goto corrupt;
                if(ae == 1)
                    src_plen += 96;
                ND_PRINT((ndo, "(%u hops) for (%s, ",
                          hopc, format_prefix(ndo, prefix, plen)));
                ND_PRINT((ndo, "%s) seqno %u id %s",
                          format_prefix(ndo, src_prefix, src_plen),
                          seqno, format_id(router_id)));
            }
        }
            break;

        default:
            if (!ndo->ndo_vflag)
                ND_PRINT((ndo, " unknown"));
            else
                ND_PRINT((ndo, "\n\tUnknown message type %d", type));
        }
        i += len + 2;
    }
    return;

 trunc:
    ND_PRINT((ndo, " %s", tstr));
    return;

 corrupt:
    ND_PRINT((ndo, " (corrupt)"));
    return;
}
Exemplo n.º 16
0
int
kernel_route(int operation, const unsigned char *dest, unsigned short plen,
             const unsigned char *gate, int ifindex, unsigned int metric,
             const unsigned char *newgate, int newifindex,
             unsigned int newmetric)
{
    unsigned char msg[512];
    struct rt_msghdr *rtm;
    struct sockaddr_in6 *sin6;
    struct sockaddr_in *sin;
    int rc, len, ipv4;

    char local6[1][1][16] = IN6ADDR_LOOPBACK_INIT;
    char local4[1][1][16] =
        {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}};

    /* Check that the protocol family is consistent. */
    if(plen >= 96 && v4mapped(dest)) {
        if(!v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
        ipv4 = 1;
    } else {
        if(v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
        ipv4 = 0;
    }

    if(operation == ROUTE_MODIFY && newmetric == metric && 
       memcmp(newgate, gate, 16) == 0 && newifindex == ifindex)
      return 0;

    if(operation == ROUTE_MODIFY) {
        metric = newmetric;
        gate = newgate;
        ifindex = newifindex;
    }

    kdebugf("kernel_route: %s %s/%d metric %d dev %d nexthop %s\n",
            operation == ROUTE_ADD ? "add" :
            operation == ROUTE_FLUSH ? "flush" : "change",
            format_address(dest), plen, metric, ifindex,
            format_address(gate));

    if(kernel_socket < 0) kernel_setup_socket(1);

    memset(&msg, 0, sizeof(msg));
    rtm = (struct rt_msghdr *)msg;
    rtm->rtm_version = RTM_VERSION;
    switch(operation) {
    case ROUTE_FLUSH:
        rtm->rtm_type = RTM_DELETE; break;
    case ROUTE_ADD:
        rtm->rtm_type = RTM_ADD; break;
    case ROUTE_MODIFY: 
        rtm->rtm_type = RTM_CHANGE; break;
    default: 
        return -1;
    };
    rtm->rtm_index = ifindex;
    rtm->rtm_flags = RTF_UP | RTF_PROTO2;
    if(plen == 128) rtm->rtm_flags |= RTF_HOST;
    /*     if(memcmp(nexthop->id, dest, 16) == 0) { */
    /*         rtm -> rtm_flags |= RTF_LLINFO; */
    /*         rtm -> rtm_flags |= RTF_CLONING; */
    /*     } else { */
    rtm->rtm_flags |= RTF_GATEWAY;
    /*     } */
    if(metric == KERNEL_INFINITY) {
        rtm->rtm_flags |= RTF_BLACKHOLE;
        if(ifindex_lo < 0) {
            ifindex_lo = if_nametoindex("lo0");
            if(ifindex_lo <= 0)
                return -1;
        }
        rtm->rtm_index = ifindex_lo;      
    }
    rtm->rtm_seq = ++seq;
    rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
    if(!(operation == ROUTE_MODIFY && plen == 128)) {
        rtm->rtm_addrs |= RTA_NETMASK;
    }

#define push_sockaddr_in(ptr, offset) \
    do { (ptr) = (struct sockaddr_in *)((char *)(ptr) + (offset)); \
         (ptr)->sin_len = sizeof(struct sockaddr_in); \
         (ptr)->sin_family = AF_INET; } while (0)

#define get_sin_addr(dst,src) \
    do { memcpy((dst), (src) + 12, 4); } while (0)

#define push_sockaddr_in6(ptr, offset) \
    do { (ptr) = (struct sockaddr_in6 *)((char *)(ptr) + (offset)); \
         (ptr)->sin6_len = sizeof(struct sockaddr_in6); \
         (ptr)->sin6_family = AF_INET6; } while (0)

#define get_sin6_addr(dst,src) \
    do { memcpy((dst), (src), 16); } while (0)

    /* KAME ipv6 stack does not support IPv4 mapped IPv6, so we have to
     * duplicate the codepath */
    if(ipv4) {
        sin = (struct sockaddr_in *)msg;
        /* destination */
        push_sockaddr_in(sin, sizeof(*rtm));
        get_sin_addr(&(sin->sin_addr), dest);
        /* gateway */
        push_sockaddr_in(sin, ROUNDUP(sin->sin_len));
        if (metric == KERNEL_INFINITY)
            get_sin_addr(&(sin->sin_addr),**local4);
        else
            get_sin_addr(&(sin->sin_addr),gate);
        /* netmask */
        if((rtm->rtm_addrs | RTA_NETMASK) != 0) {
            struct in6_addr tmp_sin6_addr;
            push_sockaddr_in(sin, ROUNDUP(sin->sin_len));
            plen2mask(plen, &tmp_sin6_addr);
            get_sin_addr(&(sin->sin_addr), (char *)&tmp_sin6_addr);
        }
        len = (char *)sin + ROUNDUP(sin->sin_len) - (char *)msg;
    } else {
        sin6 = (struct sockaddr_in6 *)msg;
        /* destination */
        push_sockaddr_in6(sin6, sizeof(*rtm));
        get_sin6_addr(&(sin6->sin6_addr), dest);
        /* gateway */
        push_sockaddr_in6(sin6, ROUNDUP(sin6->sin6_len));
        if (metric == KERNEL_INFINITY)
            get_sin6_addr(&(sin6->sin6_addr),**local6);
        else
            get_sin6_addr(&(sin6->sin6_addr),gate);
        if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr))
            SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex);
        /* netmask */
        if((rtm->rtm_addrs | RTA_NETMASK) != 0) {
            push_sockaddr_in6(sin6, ROUNDUP(sin6->sin6_len));
            plen2mask(plen, &sin6->sin6_addr);
        }
        len = (char *)sin6 + ROUNDUP(sin6->sin6_len) - (char *)msg;
    }
    rtm->rtm_msglen = len;

    rc = write(kernel_socket, msg, rtm->rtm_msglen);
    if (rc < rtm->rtm_msglen)
        return -1;

    return 1;
}
Exemplo n.º 17
0
static int
filter_addresses(struct nlmsghdr *nh, void *data)
{
    int rc;
    int maxroutes = 0;
    struct kernel_route *routes = NULL;
    struct in6_addr addr;
    int *found = NULL;
    int len;
    struct ifaddrmsg *ifa;
    char ifname[IFNAMSIZ];
    int ifindex = 0;
    int ll = 0;

    if (data) {
        void **args = (void **)data;
        maxroutes = *(int *)args[0];
        routes = (struct kernel_route*)args[1];
        found = (int *)args[2];
        ifindex = args[3] ? *(int*)args[3] : 0;
        ll = args[4] ? !!*(int*)args[4] : 0;
    }

    len = nh->nlmsg_len;

    if (data && *found >= maxroutes)
        return 0;

    if (nh->nlmsg_type != RTM_NEWADDR &&
            (data || nh->nlmsg_type != RTM_DELADDR))
        return 0;

    ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
    len -= NLMSG_LENGTH(0);

    rc = parse_addr_rta(ifa, len, &addr);
    if (rc < 0)
        return 0;

    if (ll == !IN6_IS_ADDR_LINKLOCAL(&addr))
        return 0;

    if (ifindex && ifa->ifa_index != ifindex)
        return 0;

    kdebugf("found address on interface %s(%d): %s\n",
            if_indextoname(ifa->ifa_index, ifname), ifa->ifa_index,
            format_address(addr.s6_addr));

    if (data) {
        struct kernel_route *route = &routes[*found];
        memcpy(route->prefix, addr.s6_addr, 16);
        route->plen = 128;
        route->metric = 0;
        route->ifindex = ifa->ifa_index;
        route->proto = RTPROT_BABEL_LOCAL;
        memset(route->gw, 0, 16);
        *found = (*found)+1;
    }

    return 1;
}
Exemplo n.º 18
0
int
kernel_route(int operation, const unsigned char *dest, unsigned short plen,
             const unsigned char *gate, int ifindex, unsigned int metric,
             const unsigned char *newgate, int newifindex,
             unsigned int newmetric)
{

    union { char raw[1024]; struct nlmsghdr nh; } buf;
    struct rtmsg *rtm;
    struct rtattr *rta;
    int len = sizeof(buf.raw);
    int rc, ipv4;

    if(!nl_setup) {
        fprintf(stderr,"kernel_route: netlink not initialized.\n");
        errno = EIO;
        return -1;
    }

    /* if the socket has been closed after an IO error, */
    /* we try to re-open it. */
    if(nl_command.sock < 0) {
        rc = netlink_socket(&nl_command, 0);
        if(rc < 0) {
            int olderrno = errno;
            perror("kernel_route: netlink_socket()");
            errno = olderrno;
            return -1;
        }
    }

    /* Check that the protocol family is consistent. */
    if(plen >= 96 && v4mapped(dest)) {
        if(!v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
    } else {
        if(v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
    }

    ipv4 = v4mapped(gate);

    if(operation == ROUTE_MODIFY) {
        if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
           newifindex == ifindex)
            return 0;
        /* It would be better to add the new route before removing the
           old one, to avoid losing packets.  However, this causes
           problems with non-multipath kernels, which sometimes
           silently fail the request, causing "stuck" routes.  Let's
           stick with the naive approach, and hope that the window is
           small enough to be negligible. */
        kernel_route(ROUTE_FLUSH, dest, plen,
                     gate, ifindex, metric,
                     NULL, 0, 0);
        rc = kernel_route(ROUTE_ADD, dest, plen,
                          newgate, newifindex, newmetric,
                          NULL, 0, 0);
        if(rc < 0) {
            if(errno == EEXIST)
                rc = 1;
            /* Should we try to re-install the flushed route on failure?
               Error handling is hard. */
        }
        return rc;
    }

    kdebugf("kernel_route: %s %s/%d metric %d dev %d nexthop %s\n",
           operation == ROUTE_ADD ? "add" :
           operation == ROUTE_FLUSH ? "flush" : "???",
           format_address(dest), plen, metric, ifindex,
           format_address(gate));

    /* Unreachable default routes cause all sort of weird interactions;
       ignore them. */
    if(metric >= KERNEL_INFINITY && (plen == 0 || (ipv4 && plen == 96)))
        return 0;

    memset(buf.raw, 0, sizeof(buf.raw));
    if(operation == ROUTE_ADD) {
        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
        buf.nh.nlmsg_type = RTM_NEWROUTE;
    } else {
        buf.nh.nlmsg_flags = NLM_F_REQUEST;
        buf.nh.nlmsg_type = RTM_DELROUTE;
    }

    rtm = NLMSG_DATA(&buf.nh);
    rtm->rtm_family = ipv4 ? AF_INET : AF_INET6;
    rtm->rtm_dst_len = ipv4 ? plen - 96 : plen;
    rtm->rtm_table = export_table;
    rtm->rtm_scope = RT_SCOPE_UNIVERSE;
    if(metric < KERNEL_INFINITY)
        rtm->rtm_type = RTN_UNICAST;
    else
        rtm->rtm_type = RTN_UNREACHABLE;
    rtm->rtm_protocol = RTPROT_BABEL;
    rtm->rtm_flags |= RTNH_F_ONLINK;

    rta = RTM_RTA(rtm);

    if(ipv4) {
        rta = RTA_NEXT(rta, len);
        rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
        rta->rta_type = RTA_DST;
        memcpy(RTA_DATA(rta), dest + 12, sizeof(struct in_addr));
    } else {
        rta = RTA_NEXT(rta, len);
        rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
        rta->rta_type = RTA_DST;
        memcpy(RTA_DATA(rta), dest, sizeof(struct in6_addr));
    }

    rta = RTA_NEXT(rta, len);
    rta->rta_len = RTA_LENGTH(sizeof(int));
    rta->rta_type = RTA_PRIORITY;

    if(metric < KERNEL_INFINITY) {
        *(int*)RTA_DATA(rta) = metric;
        rta = RTA_NEXT(rta, len);
        rta->rta_len = RTA_LENGTH(sizeof(int));
        rta->rta_type = RTA_OIF;
        *(int*)RTA_DATA(rta) = ifindex;

        if(ipv4) {
            rta = RTA_NEXT(rta, len);
            rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
            rta->rta_type = RTA_GATEWAY;
            memcpy(RTA_DATA(rta), gate + 12, sizeof(struct in_addr));
        } else {
            rta = RTA_NEXT(rta, len);
            rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
            rta->rta_type = RTA_GATEWAY;
            memcpy(RTA_DATA(rta), gate, sizeof(struct in6_addr));
        }
    } else {
        *(int*)RTA_DATA(rta) = -1;
    }
    buf.nh.nlmsg_len = (char*)rta + rta->rta_len - buf.raw;

    return netlink_talk(&buf.nh);
}
Exemplo n.º 19
0
int
kernel_route(int operation, const unsigned char *dest, unsigned short plen,
             const unsigned char *gate, int ifindex, unsigned int metric,
             const unsigned char *newgate, int newifindex,
             unsigned int newmetric)
{
    struct {
      struct rt_msghdr m_rtm;
      char m_space[512];
    } msg;
    char *data = msg.m_space;
    int rc, ipv4;

    char local6[1][1][16] = IN6ADDR_LOOPBACK_INIT;
    char local4[1][1][16] =
        {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}};

    /* Check that the protocol family is consistent. */
    if(plen >= 96 && v4mapped(dest)) {
        if(!v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
        ipv4 = 1;
    } else {
        if(v4mapped(gate)) {
            errno = EINVAL;
            return -1;
        }
        ipv4 = 0;
    }

    if(operation == ROUTE_MODIFY && newmetric == metric && 
       memcmp(newgate, gate, 16) == 0 && newifindex == ifindex)
      return 0;


    if(operation == ROUTE_MODIFY) {

        /* Avoid atomic route changes that is buggy on OS X. */
        kernel_route(ROUTE_FLUSH, dest, plen,
                     gate, ifindex, metric,
                     NULL, 0, 0);
        return kernel_route(ROUTE_ADD, dest, plen,
                            newgate, newifindex, newmetric,
                            NULL, 0, 0);

    }

    kdebugf("kernel_route: %s %s/%d metric %d dev %d nexthop %s\n",
            operation == ROUTE_ADD ? "add" :
            operation == ROUTE_FLUSH ? "flush" : "change",
            format_address(dest), plen, metric, ifindex,
            format_address(gate));

    if(kernel_socket < 0) kernel_setup_socket(1);

    memset(&msg, 0, sizeof(msg));
    msg.m_rtm.rtm_version = RTM_VERSION;
    switch(operation) {
    case ROUTE_FLUSH:
        msg.m_rtm.rtm_type = RTM_DELETE; break;
    case ROUTE_ADD:
        msg.m_rtm.rtm_type = RTM_ADD; break;
    case ROUTE_MODIFY:
        msg.m_rtm.rtm_type = RTM_CHANGE; break;
    default:
        return -1;
    };
    msg.m_rtm.rtm_index = ifindex;
    msg.m_rtm.rtm_flags = RTF_UP | RTF_PROTO2;
    if(plen == 128) msg.m_rtm.rtm_flags |= RTF_HOST;
    if(metric == KERNEL_INFINITY) {
        msg.m_rtm.rtm_flags |= RTF_BLACKHOLE;
        if(ifindex_lo < 0) {
            ifindex_lo = if_nametoindex("lo0");
            if(ifindex_lo <= 0)
                return -1;
        }
        msg.m_rtm.rtm_index = ifindex_lo;
    }
    msg.m_rtm.rtm_seq = ++seq;
    msg.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
    if(plen != 128) msg.m_rtm.rtm_addrs |= RTA_NETMASK;

#define PUSHEUI(ifindex) \
    do { char ifname[IFNAMSIZ]; \
         struct sockaddr_dl *sdl = (struct sockaddr_dl*) data; \
         if(!if_indextoname((ifindex), ifname))  \
             return -1; \
         if(get_sdl(sdl, ifname) < 0)   \
             return -1; \
         data = data + ROUNDUP(sdl->sdl_len); \
    } while (0)

#define PUSHADDR(src) \
    do { struct sockaddr_in *sin = (struct sockaddr_in*) data; \
         sin->sin_len = sizeof(struct sockaddr_in);  \
         sin->sin_family = AF_INET; \
         memcpy(&sin->sin_addr, (src) + 12, 4); \
         data = data + ROUNDUP(sin->sin_len); \
    } while (0)

#define PUSHADDR6(src) \
    do { struct sockaddr_in6 *sin6 = (struct sockaddr_in6*) data; \
         sin6->sin6_len = sizeof(struct sockaddr_in6); \
         sin6->sin6_family = AF_INET6; \
         memcpy(&sin6->sin6_addr, (src), 16); \
         if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) \
            SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex); \
         data = data + ROUNDUP(sin6->sin6_len); \
    } while (0)

    /* KAME ipv6 stack does not support IPv4 mapped IPv6, so we have to
     * duplicate the codepath */
    if(ipv4) {

        PUSHADDR(dest);
        if (metric == KERNEL_INFINITY) {
            PUSHADDR(**local4);
        } else if(plen == 128 && memcmp(dest+12, gate+12, 4) == 0) {
#if defined(RTF_CLONING)
            msg.m_rtm.rtm_flags |= RTF_CLONING;
#endif
            PUSHEUI(ifindex);
        } else {
            msg.m_rtm.rtm_flags |= RTF_GATEWAY;
            PUSHADDR(gate);
        }
        if((msg.m_rtm.rtm_addrs & RTA_NETMASK) != 0) {
            struct in6_addr tmp_sin6_addr;
            plen2mask(plen, &tmp_sin6_addr);
            PUSHADDR((char *)&tmp_sin6_addr);
        }

    } else {

        PUSHADDR6(dest);
        if (metric == KERNEL_INFINITY) {
            PUSHADDR6(**local6);
        } else {
            msg.m_rtm.rtm_flags |= RTF_GATEWAY;
            PUSHADDR6(gate);
        }
        if((msg.m_rtm.rtm_addrs & RTA_NETMASK) != 0) {
            struct in6_addr tmp_sin6_addr;
            plen2mask(plen, &tmp_sin6_addr);
            PUSHADDR6((char*)&tmp_sin6_addr);
        }

    }

#undef PUSHEUI
#undef PUSHADDR
#undef PUSHADDR6

    msg.m_rtm.rtm_msglen = data - (char *)&msg;
    rc = write(kernel_socket, (char*)&msg, msg.m_rtm.rtm_msglen);
    if (rc < msg.m_rtm.rtm_msglen)
        return -1;

    return 1;
}