BSD 4_3_Net_2 release
[unix-history] / usr / src / sbin / routed / startup.c
index 1747b66..f88d593 100644 (file)
+/*
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  4.4 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)startup.c  5.19 (Berkeley) 2/28/91";
+#endif /* not lint */
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
+#include <sys/ioctl.h>
 #include <net/if.h>
 #include <net/if.h>
-#include <nlist.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include "pathnames.h"
 
 struct interface *ifnet;
 
 struct interface *ifnet;
-int    kmem = -1;
+struct interface **ifnext = &ifnet;
 int    lookforinterfaces = 1;
 int    lookforinterfaces = 1;
-int    performnlist = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
-
-struct nlist nl[] = {
-#define        N_IFNET         0
-       { "_ifnet" },
-       { "" },
-};
+int    foundloopback;                  /* valid flag for loopaddr */
+struct sockaddr loopaddr;              /* our address on loopback */
 
 /*
 
 /*
- * Probe the kernel through /dev/kmem to find the network
- * interfaces which have configured themselves.  If the
- * interface is present but not yet up (for example an
+ * Find the network interfaces which have configured themselves.
+ * If the interface is present but not yet up (for example an
  * ARPANET IMP), set the lookforinterfaces flag so we'll
  * come back later and look again.
  */
 ifinit()
 {
  * ARPANET IMP), set the lookforinterfaces flag so we'll
  * come back later and look again.
  */
 ifinit()
 {
-       struct interface *ifp;
-       struct ifnet ifs, *next;
-       char name[32], *cp, *index();
+       struct interface ifs, *ifp;
+       int s;
+       char buf[BUFSIZ], *cp, *cplim;
+        struct ifconf ifc;
+        struct ifreq ifreq, *ifr;
+        struct sockaddr_in *sin;
+       u_long i;
 
 
-       if (performnlist) {
-               nlist("/vmunix", nl);
-               if (nl[N_IFNET].n_value == 0) {
-                       printf("ifnet: not in namelist\n");
-                       goto bad;
-               }
-               performnlist = 0;
-       }
-       if (kmem < 0) {
-               kmem = open("/dev/kmem", 0);
-               if (kmem < 0) {
-                       perror("/dev/kmem");
-                       goto bad;
-               }
-       }
-       if (lseek(kmem, (long)nl[N_IFNET].n_value, 0) == -1 ||
-           read(kmem, (char *)&next, sizeof (next)) != sizeof (next)) {
-               printf("ifnet: error reading kmem\n");
-               goto bad;
+       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               syslog(LOG_ERR, "socket: %m");
+               close(s);
+                return;
        }
        }
+        ifc.ifc_len = sizeof (buf);
+        ifc.ifc_buf = buf;
+        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+                syslog(LOG_ERR, "ioctl (get interface configuration)");
+               close(s);
+                return;
+        }
+        ifr = ifc.ifc_req;
        lookforinterfaces = 0;
        lookforinterfaces = 0;
-       while (next) {
-               if (lseek(kmem, (long)next, 0) == -1 ||
-                   read(kmem, (char *)&ifs, sizeof (ifs)) != sizeof (ifs)) {
-                       perror("read");
-                       goto bad;
-               }
-               next = ifs.if_next;
-               if ((ifs.if_flags & IFF_UP) == 0) {
+#ifdef RTM_ADD
+#define max(a, b) (a > b ? a : b)
+#define size(p)        max((p).sa_len, sizeof(p))
+#else
+#define size(p) (sizeof (p))
+#endif
+       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+       for (cp = buf; cp < cplim;
+                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+               ifr = (struct ifreq *)cp;
+               bzero((char *)&ifs, sizeof(ifs));
+               ifs.int_addr = ifr->ifr_addr;
+               ifreq = *ifr;
+                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+                        syslog(LOG_ERR, "%s: ioctl (get interface flags)",
+                           ifr->ifr_name);
+                        continue;
+                }
+               ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
+               if ((ifs.int_flags & IFF_UP) == 0 ||
+                   ifr->ifr_addr.sa_family == AF_UNSPEC) {
                        lookforinterfaces = 1;
                        continue;
                }
                        lookforinterfaces = 1;
                        continue;
                }
-               /* already known to us? */
-               if (if_ifwithaddr(&ifs.if_addr))
-                       continue;
                /* argh, this'll have to change sometime */
                /* argh, this'll have to change sometime */
-               if (ifs.if_addr.sa_family != AF_INET)
+               if (ifs.int_addr.sa_family != AF_INET)
                        continue;
                        continue;
-               /* no one cares about software loopback interfaces */
-               if (ifs.if_net == LOOPBACKNET)
+                if (ifs.int_flags & IFF_POINTOPOINT) {
+                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
+                                   ifr->ifr_name);
+                                continue;
+                       }
+                       if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
+                       }
+                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+               }
+               /*
+                * already known to us?
+                * This allows multiple point-to-point links
+                * to share a source address (possibly with one
+                * other link), but assumes that there will not be
+                * multiple links with the same destination address.
+                */
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (if_ifwithdstaddr(&ifs.int_dstaddr))
+                               continue;
+               } else if (if_ifwithaddr(&ifs.int_addr))
+                       continue;
+               if (ifs.int_flags & IFF_LOOPBACK) {
+                       ifs.int_flags |= IFF_PASSIVE;
+                       foundloopback = 1;
+                       loopaddr = ifs.int_addr;
+                       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+                           if (ifp->int_flags & IFF_POINTOPOINT)
+                               add_ptopt_localrt(ifp);
+               }
+                if (ifs.int_flags & IFF_BROADCAST) {
+                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
+                                   ifr->ifr_name);
+                                continue;
+                        }
+#ifndef sun
+                       ifs.int_broadaddr = ifreq.ifr_broadaddr;
+#else
+                       ifs.int_broadaddr = ifreq.ifr_addr;
+#endif
+               }
+#ifdef SIOCGIFMETRIC
+               if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
+                       syslog(LOG_ERR, "%s: ioctl (get metric)",
+                           ifr->ifr_name);
+                       ifs.int_metric = 0;
+               } else
+                       ifs.int_metric = ifreq.ifr_metric;
+#else
+               ifs.int_metric = 0;
+#endif
+               /*
+                * Use a minimum metric of one;
+                * treat the interface metric (default 0)
+                * as an increment to the hop count of one.
+                */
+               ifs.int_metric++;
+               if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+                       syslog(LOG_ERR, "%s: ioctl (get netmask)",
+                           ifr->ifr_name);
                        continue;
                        continue;
+               }
+               sin = (struct sockaddr_in *)&ifreq.ifr_addr;
+               ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
+               sin = (struct sockaddr_in *)&ifs.int_addr;
+               i = ntohl(sin->sin_addr.s_addr);
+               if (IN_CLASSA(i))
+                       ifs.int_netmask = IN_CLASSA_NET;
+               else if (IN_CLASSB(i))
+                       ifs.int_netmask = IN_CLASSB_NET;
+               else
+                       ifs.int_netmask = IN_CLASSC_NET;
+               ifs.int_net = i & ifs.int_netmask;
+               ifs.int_subnet = i & ifs.int_subnetmask;
+               if (ifs.int_subnetmask != ifs.int_netmask)
+                       ifs.int_flags |= IFF_SUBNET;
                ifp = (struct interface *)malloc(sizeof (struct interface));
                if (ifp == 0) {
                        printf("routed: out of memory\n");
                        break;
                }
                ifp = (struct interface *)malloc(sizeof (struct interface));
                if (ifp == 0) {
                        printf("routed: out of memory\n");
                        break;
                }
+               *ifp = ifs;
                /*
                 * Count the # of directly connected networks
                 * and point to point links which aren't looped
                 * back to ourself.  This is used below to
                 * decide if we should be a routing ``supplier''.
                 */
                /*
                 * Count the # of directly connected networks
                 * and point to point links which aren't looped
                 * back to ourself.  This is used below to
                 * decide if we should be a routing ``supplier''.
                 */
-               if ((ifs.if_flags & IFF_POINTOPOINT) == 0 ||
-                   if_ifwithaddr(&ifs.if_dstaddr) == 0)
+               if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
+                   ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
+                   if_ifwithaddr(&ifs.int_dstaddr) == 0))
                        externalinterfaces++;
                        externalinterfaces++;
-               lseek(kmem, ifs.if_name, 0);
-               read(kmem, name, sizeof (name));
-               name[sizeof (name) - 1] = '\0';
-               cp = index(name, '\0');
-               *cp++ = ifs.if_unit + '0';
-               *cp = '\0';
-               ifp->int_name = malloc(strlen(name) + 1);
+               /*
+                * If we have a point-to-point link, we want to act
+                * as a supplier even if it's our only interface,
+                * as that's the only way our peer on the other end
+                * can tell that the link is up.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
+                       supplier = 1;
+               ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
-                       goto bad;               /* ??? */
+                       syslog(LOG_ERR, "routed: ifinit: out of memory\n");
+                       close(s);
+                       return;
                }
                }
-               strcpy(ifp->int_name, name);
-               ifp->int_addr = ifs.if_addr;
-               ifp->int_flags = ifs.if_flags | IFF_INTERFACE;
-               /* this works because broadaddr overlaps dstaddr */
-               ifp->int_broadaddr = ifs.if_broadaddr;
-               ifp->int_net = ifs.if_net;
-               ifp->int_metric = 0;
-               ifp->int_next = ifnet;
-               ifnet = ifp;
+               strcpy(ifp->int_name, ifr->ifr_name);
+               *ifnext = ifp;
+               ifnext = &ifp->int_next;
                traceinit(ifp);
                addrouteforif(ifp);
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
                traceinit(ifp);
                addrouteforif(ifp);
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
-       return;
-bad:
-       sleep(60);
-       close(kmem), close(s);
-       execv("/etc/routed", argv0);
-       _exit(0177);
+       close(s);
 }
 
 }
 
+/*
+ * Add route for interface if not currently installed.
+ * Create route to other end if a point-to-point link,
+ * otherwise a route to this (sub)network.
+ * INTERNET SPECIFIC.
+ */
 addrouteforif(ifp)
 addrouteforif(ifp)
-       struct interface *ifp;
+       register struct interface *ifp;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
-       int state, metric;
-       struct rt_entry *rt;
+       int state;
+       register struct rt_entry *rt;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
                dst = &ifp->int_dstaddr;
        else {
                bzero((char *)&net, sizeof (net));
                net.sin_family = AF_INET;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
                dst = &ifp->int_dstaddr;
        else {
                bzero((char *)&net, sizeof (net));
                net.sin_family = AF_INET;
-               net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+               net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
                dst = (struct sockaddr *)&net;
        }
                dst = (struct sockaddr *)&net;
        }
-       rt = rtlookup(dst);
-       rtadd(dst, &ifp->int_addr, ifp->int_metric,
-               ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
+       rt = rtfind(dst);
+       if (rt &&
+           (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
+               return;
        if (rt)
                rtdelete(rt);
        if (rt)
                rtdelete(rt);
+       /*
+        * If interface on subnetted network,
+        * install route to network as well.
+        * This is meant for external viewers.
+        */
+       if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
+               struct in_addr subnet;
+
+               subnet = net.sin_addr;
+               net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+               rt = rtfind(dst);
+               if (rt == 0)
+                       rtadd(dst, &ifp->int_addr, ifp->int_metric,
+                           ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
+                           RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
+               else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == 
+                   (RTS_INTERNAL|RTS_SUBNET) &&
+                   ifp->int_metric < rt->rt_metric)
+                       rtchange(rt, &rt->rt_router, ifp->int_metric);
+               net.sin_addr = subnet;
+       }
+       if (ifp->int_transitions++ > 0)
+               syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
+       state = ifp->int_flags &
+           (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
+       if (ifp->int_flags & IFF_POINTOPOINT &&
+           (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
+           ifp->int_netmask) != ifp->int_net)
+               state &= ~RTS_SUBNET;
+       if (ifp->int_flags & IFF_LOOPBACK)
+               state |= RTS_EXTERNAL;
+       rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
+       if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
+               add_ptopt_localrt(ifp);
+}
+
+/*
+ * Add route to local end of point-to-point using loopback.
+ * If a route to this network is being sent to neighbors on other nets,
+ * mark this route as subnet so we don't have to propagate it too.
+ */
+add_ptopt_localrt(ifp)
+       register struct interface *ifp;
+{
+       struct rt_entry *rt;
+       struct sockaddr *dst;
+       struct sockaddr_in net;
+       int state;
+
+       state = RTS_INTERFACE | RTS_PASSIVE;
+
+       /* look for route to logical network */
+       bzero((char *)&net, sizeof (net));
+       net.sin_family = AF_INET;
+       net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+       dst = (struct sockaddr *)&net;
+       rt = rtfind(dst);
+       if (rt && rt->rt_state & RTS_INTERNAL)
+               state |= RTS_SUBNET;
+
+       dst = &ifp->int_addr;
+       if (rt = rtfind(dst)) {
+               if (rt && rt->rt_state & RTS_INTERFACE)
+                       return;
+               rtdelete(rt);
+       }
+       rtadd(dst, &loopaddr, 1, state);
 }
 
 /*
 }
 
 /*
@@ -157,6 +339,8 @@ addrouteforif(ifp)
  * not marked passive are treated as if they were directly
  * connected -- they're added into the interface list so we'll
  * send them routing updates.
  * not marked passive are treated as if they were directly
  * connected -- they're added into the interface list so we'll
  * send them routing updates.
+ *
+ * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
  */
 gwkludge()
 {
  */
 gwkludge()
 {
@@ -164,9 +348,10 @@ gwkludge()
        FILE *fp;
        char *type, *dname, *gname, *qual, buf[BUFSIZ];
        struct interface *ifp;
        FILE *fp;
        char *type, *dname, *gname, *qual, buf[BUFSIZ];
        struct interface *ifp;
-       int metric;
+       int metric, n;
+       struct rt_entry route;
 
 
-       fp = fopen("/etc/gateways", "r");
+       fp = fopen(_PATH_GATEWAYS, "r");
        if (fp == NULL)
                return;
        qual = buf;
        if (fp == NULL)
                return;
        qual = buf;
@@ -175,17 +360,51 @@ gwkludge()
        type = buf + (((BUFSIZ - 64) * 2) / 3);
        bzero((char *)&dst, sizeof (dst));
        bzero((char *)&gate, sizeof (gate));
        type = buf + (((BUFSIZ - 64) * 2) / 3);
        bzero((char *)&dst, sizeof (dst));
        bzero((char *)&gate, sizeof (gate));
-       /* format: {net | host} XX gateway XX metric DD [passive]\n */
+       bzero((char *)&route, sizeof(route));
+/* format: {net | host} XX gateway XX metric DD [passive | external]\n */
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
                type, dname, gname, &metric, qual)
        for (;;) {
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
                type, dname, gname, &metric, qual)
        for (;;) {
-               if (readentry(fp) == EOF)
+               if ((n = readentry(fp)) == EOF)
                        break;
                if (!getnetorhostname(type, dname, &dst))
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
                        break;
                if (!getnetorhostname(type, dname, &dst))
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
+               if (metric == 0)                        /* XXX */
+                       metric = 1;
+               if (strcmp(qual, "passive") == 0) {
+                       /*
+                        * Passive entries aren't placed in our tables,
+                        * only the kernel's, so we don't copy all of the
+                        * external routing information within a net.
+                        * Internal machines should use the default
+                        * route to a suitable gateway (like us).
+                        */
+                       route.rt_dst = *(struct sockaddr *) &dst;
+                       route.rt_router = *(struct sockaddr *) &gate;
+                       route.rt_flags = RTF_UP;
+                       if (strcmp(type, "host") == 0)
+                               route.rt_flags |= RTF_HOST;
+                       if (metric)
+                               route.rt_flags |= RTF_GATEWAY;
+                       (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
+                       continue;
+               }
+               if (strcmp(qual, "external") == 0) {
+                       /*
+                        * Entries marked external are handled
+                        * by other means, e.g. EGP,
+                        * and are placed in our tables only
+                        * to prevent overriding them
+                        * with something else.
+                        */
+                       rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
+                       continue;
+               }
+               /* assume no duplicate entries */
+               externalinterfaces++;
                ifp = (struct interface *)malloc(sizeof (*ifp));
                bzero((char *)ifp, sizeof (*ifp));
                ifp->int_flags = IFF_REMOTE;
                ifp = (struct interface *)malloc(sizeof (*ifp));
                bzero((char *)ifp, sizeof (*ifp));
                ifp->int_flags = IFF_REMOTE;
@@ -195,11 +414,6 @@ gwkludge()
                        ifp->int_flags |= IFF_POINTOPOINT;
                        ifp->int_dstaddr = *((struct sockaddr *)&dst);
                }
                        ifp->int_flags |= IFF_POINTOPOINT;
                        ifp->int_dstaddr = *((struct sockaddr *)&dst);
                }
-               if (strcmp(qual, "passive") == 0)
-                       ifp->int_flags |= IFF_PASSIVE;
-               else
-                       /* assume no duplicate entries */
-                       externalinterfaces++;
                ifp->int_addr = *((struct sockaddr *)&gate);
                ifp->int_metric = metric;
                ifp->int_next = ifnet;
                ifp->int_addr = *((struct sockaddr *)&gate);
                ifp->int_metric = metric;
                ifp->int_next = ifnet;
@@ -224,6 +438,15 @@ getnetorhostname(type, name, sin)
                        if (np->n_addrtype != AF_INET)
                                return (0);
                        n = np->n_net;
                        if (np->n_addrtype != AF_INET)
                                return (0);
                        n = np->n_net;
+                       /*
+                        * getnetbyname returns right-adjusted value.
+                        */
+                       if (n < 128)
+                               n <<= IN_CLASSA_NSHIFT;
+                       else if (n < 65536)
+                               n <<= IN_CLASSB_NSHIFT;
+                       else
+                               n <<= IN_CLASSC_NSHIFT;
                }
                sin->sin_family = AF_INET;
                sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
                }
                sin->sin_family = AF_INET;
                sin->sin_addr = inet_makeaddr(n, INADDR_ANY);