Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net deal with failure of malloc NOWAIT by restarting aft...



details:   https://anonhg.NetBSD.org/src/rev/22cacb9d688b
branches:  trunk
changeset: 471491:22cacb9d688b
user:      chopps <chopps%NetBSD.org@localhost>
date:      Fri Apr 02 17:22:21 1999 +0000

description:
deal with failure of malloc NOWAIT by restarting after mallocing with WAIT.
don't write beyond the users given buffer size (this happened if there was
        enough space for the initial malloc to succeed).

diffstat:

 sys/net/rtsock.c |  84 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 63 insertions(+), 21 deletions(-)

diffs (179 lines):

diff -r 5381eb328cd5 -r 22cacb9d688b sys/net/rtsock.c
--- a/sys/net/rtsock.c  Fri Apr 02 16:05:55 1999 +0000
+++ b/sys/net/rtsock.c  Fri Apr 02 17:22:21 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtsock.c,v 1.28 1998/12/12 17:26:09 christos Exp $     */
+/*     $NetBSD: rtsock.c,v 1.29 1999/04/02 17:22:21 chopps Exp $       */
 
 /*
  * Copyright (c) 1988, 1991, 1993
@@ -58,12 +58,19 @@
 struct sockproto route_proto = { PF_ROUTE, };
 
 struct walkarg {
-       int     w_op, w_arg, w_given, w_needed, w_tmemsize;
-       caddr_t w_where, w_tmem;
+       int     w_op;
+       int     w_arg;
+       int     w_given;
+       int     w_needed;
+       caddr_t w_where;
+       int     w_tmemsize;
+       int     w_tmemneeded;
+       caddr_t w_tmem;
 };
 
 static struct mbuf *rt_msg1 __P((int, struct rt_addrinfo *));
-static int rt_msg2 __P((int, struct rt_addrinfo *, caddr_t, struct walkarg *));
+static int rt_msg2 __P((int, struct rt_addrinfo *, caddr_t, struct walkarg *,
+    int *));
 static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
 static __inline void rt_adjustcount __P((int, int));
 
@@ -277,8 +284,8 @@
                                        ifaaddr = 0;
                            }
                        }
-                       len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
-                           (struct walkarg *)0);
+                       (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
+                           (struct walkarg *)0, &len);
                        if (len > rtm->rtm_msglen) {
                                struct rt_msghdr *new_rtm;
                                R_Malloc(new_rtm, struct rt_msghdr *, len);
@@ -288,7 +295,7 @@
                                Free(rtm); rtm = new_rtm;
                        }
                        (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
-                           (struct walkarg *)0);
+                           (struct walkarg *)0, 0);
                        rtm->rtm_flags = rt->rt_flags;
                        rtm->rtm_rmx = rt->rt_rmx;
                        rtm->rtm_addrs = info.rti_addrs;
@@ -470,12 +477,26 @@
        return (m);
 }
 
+/*
+ * rt_msg2
+ *
+ *      fills 'cp' or 'w'.w_tmem with the routing socket message and
+ *             returns the length of the message in 'lenp'.
+ *
+ * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold
+ *     the message
+ * otherwise walkarg's w_needed is updated and if the user buffer is
+ *     specified and w_needed indicates space exists the information is copied
+ *     into the temp space (w_tmem). w_tmem is [re]allocated if necessary,
+ *     if the allocation fails ENOBUFS is returned.
+ */
 static int
-rt_msg2(type, rtinfo, cp, w)
+rt_msg2(type, rtinfo, cp, w, lenp)
        int type;
        register struct rt_addrinfo *rtinfo;
        caddr_t cp;
        struct walkarg *w;
+       int *lenp;
 {
        register int i;
        int len, dlen, second_time = 0;
@@ -529,8 +550,10 @@
                                cp = rw->w_tmem;
                                second_time = 1;
                                goto again;
-                       } else
-                               rw->w_where = 0;
+                       } else {
+                               rw->w_tmemneeded = len;
+                               return (ENOBUFS);
+                       }
                }
        }
        if (cp) {
@@ -540,7 +563,9 @@
                rtm->rtm_type = type;
                rtm->rtm_msglen = len;
        }
-       return (len);
+       if (lenp)
+               *lenp = len;
+       return (0);
 }
 
 /*
@@ -687,8 +712,9 @@
                if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
                        brdaddr = rt->rt_ifa->ifa_dstaddr;
        }
-       size = rt_msg2(RTM_GET, &info, 0, w);
-       if (w->w_where && w->w_tmem) {
+       if ((error = rt_msg2(RTM_GET, &info, 0, w, &size)))
+               return (error);
+       if (w->w_where && w->w_tmem && w->w_needed <= 0) {
                register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
 
                rtm->rtm_flags = rt->rt_flags;
@@ -721,9 +747,10 @@
                        continue;
                ifa = ifp->if_addrlist.tqh_first;
                ifpaddr = ifa->ifa_addr;
-               len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
+               if ((error = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w, &len)))
+                       return (error);
                ifpaddr = 0;
-               if (w->w_where && w->w_tmem) {
+               if (w->w_where && w->w_tmem && w->w_needed <= 0) {
                        register struct if_msghdr *ifm;
 
                        ifm = (struct if_msghdr *)w->w_tmem;
@@ -742,8 +769,9 @@
                        ifaaddr = ifa->ifa_addr;
                        netmask = ifa->ifa_netmask;
                        brdaddr = ifa->ifa_dstaddr;
-                       len = rt_msg2(RTM_NEWADDR, &info, 0, w);
-                       if (w->w_where && w->w_tmem) {
+                       if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len)))
+                               return (error);
+                       if (w->w_where && w->w_tmem && w->w_needed <= 0) {
                                register struct ifa_msghdr *ifam;
 
                                ifam = (struct ifa_msghdr *)w->w_tmem;
@@ -781,12 +809,21 @@
        if (namelen != 3)
                return (EINVAL);
        af = name[0];
-       Bzero(&w, sizeof(w));
-       w.w_where = where;
+       w.w_tmemneeded = 0;
+       w.w_tmemsize = 0;
+       w.w_tmem = NULL;
+again:
+       /* we may return here if a later [re]alloc of the t_mem buffer fails */
+       if (w.w_tmemneeded) {
+               w.w_tmem = (caddr_t) malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK);
+               w.w_tmemsize = w.w_tmemneeded;
+               w.w_tmemneeded = 0;
+       }
+       w.w_op = name[1];
+       w.w_arg = name[2];
        w.w_given = *given;
        w.w_needed = 0 - w.w_given;
-       w.w_op = name[1];
-       w.w_arg = name[2];
+       w.w_where = where;
 
        s = splsoftnet();
        switch (w.w_op) {
@@ -804,6 +841,11 @@
                error = sysctl_iflist(af, &w);
        }
        splx(s);
+
+       /* check to see if we couldn't allocate memory with NOWAIT */
+       if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded)
+               goto again;
+
        if (w.w_tmem)
                free(w.w_tmem, M_RTABLE);
        w.w_needed += w.w_given;



Home | Main Index | Thread Index | Old Index