lkml.org 
[lkml]   [1998]   [Dec]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] bootp arp corruption fix (was Re: 2.2.0 Bug summary)
    From
    Date
    Alan Cox <alan@terrorserver.swansea.linux.org.uk> writes:
    > Unfixed and definitely needing fixes
    > ...
    > o bootp autobooting stuff corrupts other hosts arp stuff it seems
    > ...

    My patch to reintroduce 2.0-alike 0.0.0.0 ip address behaviour happens
    to fix this. The main point is to allow bootpc/bootp setup scripts
    that work with 2.0 to work with 2.1, and as a side effect it
    simplifies the ip autoconfiguration via bootp code, fixing this bug.

    Please consider it for 2.2, on both counts.

    Dave Wragg

    diff -rua linux-2.1.131/net/ipv4/devinet.c linux-2.1.131.bootp/net/ipv4/devinet.c
    --- linux-2.1.131/net/ipv4/devinet.c Mon Sep 7 14:27:58 1998
    +++ linux-2.1.131.bootp/net/ipv4/devinet.c Wed Dec 16 16:13:11 1998
    @@ -208,9 +208,16 @@
    {
    struct in_ifaddr *ifa1, **ifap, **last_primary;

    - if (ifa->ifa_local == 0) {
    - inet_free_ifa(ifa);
    - return 0;
    + /* Allow 0.0.0.0, but it must be the only address to avoid
    + multiple matches. */
    + if (in_dev->ifa_list) {
    + if (ifa->ifa_local == 0) {
    + inet_free_ifa(ifa);
    + return 0;
    + }
    +
    + if (in_dev->ifa_list->ifa_local == 0)
    + inet_del_ifa(in_dev, &in_dev->ifa_list, 1);
    }

    ifa->ifa_flags &= ~IFA_F_SECONDARY;
    @@ -1001,18 +1008,12 @@

    __initfunc(int inet_add_bootp_addr(struct device *dev))
    {
    - struct in_device *in_dev = dev->ip_ptr;
    struct in_ifaddr *ifa;

    - if (!in_dev && !(in_dev = inetdev_init(dev)))
    - return -ENOBUFS;
    if (!(ifa = inet_alloc_ifa()))
    return -ENOBUFS;
    - ifa->ifa_dev = in_dev;
    - in_dev->ifa_list = ifa;
    - rtmsg_ifa(RTM_NEWADDR, ifa);
    - notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
    - return 0;
    +
    + return inet_set_ifa(dev, ifa);
    }

    __initfunc(void inet_del_bootp_addr(struct device *dev))
    diff -rua linux-2.1.131/net/ipv4/fib_frontend.c linux-2.1.131.bootp/net/ipv4/fib_frontend.c
    --- linux-2.1.131/net/ipv4/fib_frontend.c Mon Sep 7 14:27:58 1998
    +++ linux-2.1.131.bootp/net/ipv4/fib_frontend.c Wed Dec 23 14:18:46 1998
    @@ -443,13 +443,13 @@
    if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
    fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);

    - if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
    + if (!(ifa->ifa_flags&IFA_F_SECONDARY) &&
    (prefix != addr || ifa->ifa_prefixlen < 32)) {
    fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
    RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);

    /* Add network specific broadcasts, when it takes a sense */
    - if (ifa->ifa_prefixlen < 31) {
    + if (!ZERONET(prefix) && ifa->ifa_prefixlen < 31) {
    fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
    fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
    }
    diff -rua linux-2.1.131/net/ipv4/ipconfig.c linux-2.1.131.bootp/net/ipv4/ipconfig.c
    --- linux-2.1.131/net/ipv4/ipconfig.c Sun Nov 8 18:40:51 1998
    +++ linux-2.1.131.bootp/net/ipv4/ipconfig.c Wed Dec 16 14:13:19 1998
    @@ -411,96 +411,6 @@
    static struct bootp_pkt *ic_recv_bootp __initdata = NULL; /* Packet being received */

    /*
    - * Dirty tricks for BOOTP packet routing. We replace the standard lookup function
    - * for the local fib by our version which does fake lookups and returns our private
    - * fib entries. Ugly, but it seems to be the simplest way to do the job.
    - */
    -
    -static void *ic_old_local_lookup __initdata = NULL; /* Old local routing table lookup function */
    -static struct fib_info *ic_bootp_tx_fib __initdata = NULL; /* Our fake fib entries */
    -static struct fib_info *ic_bootp_rx_fib __initdata = NULL;
    -
    -__initfunc(static int ic_bootp_route_lookup(struct fib_table *tb, const struct rt_key *key,
    - struct fib_result *res))
    -{
    - static u32 ic_brl_zero = 0;
    -
    - DBG(("BOOTP: Route lookup: %d:%08x -> %d:%08x: ", key->iif, key->src, key->oif, key->dst));
    - res->scope = RT_SCOPE_UNIVERSE;
    - res->prefix = &ic_brl_zero;
    - res->prefixlen = 0;
    - res->nh_sel = 0;
    - if (key->src == 0 && key->dst == 0xffffffff && key->iif == loopback_dev.ifindex) { /* Packet output */
    - DBG(("Output\n"));
    - res->type = RTN_UNICAST;
    - res->fi = ic_bootp_tx_fib;
    - } else if (key->iif && key->iif != loopback_dev.ifindex && key->oif == 0) { /* Packet input */
    - DBG(("Input\n"));
    - res->type = RTN_LOCAL;
    - res->fi = ic_bootp_rx_fib;
    - } else if (!key->iif && !key->oif && !key->src) { /* Address check by inet_addr_type() */
    - DBG(("Check\n"));
    - res->type = RTN_UNICAST;
    - res->fi = ic_bootp_tx_fib;
    - } else {
    - DBG(("Drop\n"));
    - return -EINVAL;
    - }
    - return 0;
    -}
    -
    -__initfunc(static int ic_set_bootp_route(struct ic_device *d))
    -{
    - struct fib_info *f = ic_bootp_tx_fib;
    - struct fib_nh *n = &f->fib_nh[0];
    -
    - n->nh_dev = d->dev;
    - n->nh_oif = n->nh_dev->ifindex;
    - rt_cache_flush(0);
    - return 0;
    -}
    -
    -__initfunc(static int ic_bootp_route_init(void))
    -{
    - int size = sizeof(struct fib_info) + sizeof(struct fib_nh);
    - struct fib_info *rf, *tf;
    - struct fib_nh *nh;
    -
    - if (!(rf = ic_bootp_rx_fib = kmalloc(size, GFP_KERNEL)) ||
    - !(tf = ic_bootp_tx_fib = kmalloc(size, GFP_KERNEL)))
    - return -1;
    -
    - memset(rf, 0, size);
    - rf->fib_nhs = 1;
    - nh = &rf->fib_nh[0];
    - nh->nh_scope = RT_SCOPE_UNIVERSE;
    -
    - memset(tf, 0, size);
    - rf->fib_nhs = 1;
    - nh = &rf->fib_nh[0];
    - nh->nh_dev = ic_first_dev->dev;
    - nh->nh_scope = RT_SCOPE_UNIVERSE;
    - nh->nh_oif = nh->nh_dev->ifindex;
    -
    - /* Dirty trick: replace standard routing table lookup by our function */
    - ic_old_local_lookup = local_table->tb_lookup;
    - local_table->tb_lookup = ic_bootp_route_lookup;
    -
    - return 0;
    -}
    -
    -__initfunc(static void ic_bootp_route_cleanup(void))
    -{
    - if (ic_old_local_lookup)
    - local_table->tb_lookup = ic_old_local_lookup;
    - if (ic_bootp_rx_fib)
    - kfree_s(ic_bootp_rx_fib, sizeof(struct fib_info) + sizeof(struct fib_nh));
    - if (ic_bootp_tx_fib)
    - kfree_s(ic_bootp_tx_fib, sizeof(struct fib_info) + sizeof(struct fib_nh));
    -}
    -
    -
    -/*
    * Allocation and freeing of BOOTP packet buffers.
    */
    __initfunc(static int ic_bootp_alloc(void))
    @@ -677,10 +587,9 @@
    /* Add fake zero addresses to all interfaces */
    if (ic_bootp_addrs_add() < 0)
    return -1;
    -
    - /* Initialize BOOTP routing */
    - if (ic_bootp_route_init() < 0)
    - return -1;
    +
    + /* Setting the addresses automatically creates appropriate
    + routes. */

    /* Initialize common portion of BOOTP request */
    memset(ic_xmit_bootp, 0, sizeof(struct bootp_pkt));
    @@ -699,7 +608,6 @@
    ic_bootp_xmit_sock->sk->broadcast = 1;
    ic_bootp_xmit_sock->sk->reuse = 1;
    ic_bootp_recv_sock->sk->reuse = 1;
    - ic_set_bootp_route(ic_first_dev);
    if (ic_udp_bind(ic_bootp_recv_sock, INADDR_ANY, 68) ||
    ic_udp_bind(ic_bootp_xmit_sock, INADDR_ANY, 68) ||
    ic_udp_connect(ic_bootp_xmit_sock, INADDR_BROADCAST, 67))
    @@ -718,7 +626,6 @@
    ic_udp_close(ic_bootp_recv_sock);
    ic_bootp_addrs_del();
    ic_bootp_free();
    - ic_bootp_route_cleanup();
    }


    @@ -735,7 +642,6 @@
    memset(b->hw_addr, 0, sizeof(b->hw_addr));
    memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
    b->secs = htons(jiffies / HZ);
    - ic_set_bootp_route(d);
    return ic_udp_send(ic_bootp_xmit_sock, b, sizeof(struct bootp_pkt));
    }

    diff -rua linux-2.1.131/net/ipv4/route.c linux-2.1.131.bootp/net/ipv4/route.c
    --- linux-2.1.131/net/ipv4/route.c Sun Nov 8 18:40:06 1998
    +++ linux-2.1.131.bootp/net/ipv4/route.c Wed Dec 16 14:12:40 1998
    @@ -950,6 +950,10 @@
    if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
    goto martian_destination;

    + /* Accept anything arriving at 0.0.0.0 */
    + if (in_dev->ifa_list && in_dev->ifa_list->ifa_local == 0)
    + goto local_input;
    +
    /*
    * Now we are ready to route packet.
    */

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:46    [W:3.189 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site