This is hello.c in view mode; [Download] [Up]
/* * $Header: /disk/d/src/devel/gated/dist/src/RCS/hello.c,v 2.1 92/02/24 14:12:34 jch Exp $ */ /*%Copyright%*/ /************************************************************************ * * * GateD, Release 2 * * * * Copyright (c) 1990,1991,1992 by Cornell University * * All rights reserved. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY * * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE. * * * * Royalty-free licenses to redistribute GateD Release * * 2 in whole or in part may be obtained by writing to: * * * * GateDaemon Project * * Information Technologies/Network Resources * * 143 Caldwell Hall * * Cornell University * * Ithaca, NY 14853-2602 * * * * GateD is based on Kirton's EGP, UC Berkeley's routing * * daemon (routed), and DCN's HELLO routing Protocol. * * Development of Release 2 has been supported by the * * National Science Foundation. * * * * Please forward bug fixes, enhancements and questions to the * * gated mailing list: gated-people@gated.cornell.edu. * * * * Authors: * * * * Jeffrey C Honig <jch@gated.cornell.edu> * * Scott W Brim <swb@gated.cornell.edu> * * * ************************************************************************* * * * Portions of this software may fall under the following * * copyrights: * * * * Copyright (c) 1988 Regents of the University of California. * * All rights reserved. * * * * Redistribution and use in source and binary forms are * * permitted provided that the above copyright notice and * * this paragraph are duplicated in all such forms and that * * any documentation, advertising materials, and other * * materials related to such distribution and use * * acknowledge that the software was developed by the * * University of California, Berkeley. The name of the * * University may not be used to endorse or promote * * products derived from this software without specific * * prior written permission. THIS SOFTWARE IS PROVIDED * * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, * * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * ************************************************************************/ /* * Hello output routines were taken from Mike Petry (petry@trantor.umd.edu) * Also, hello input routines were written by Bill Nesheim, Cornell * CS Dept, Currently at nesheim@think.com */ #include "include.h" #include "hello.h" #if defined(_IBMR2) #include <time.h> #endif /* defined(_IBMR2) */ #include <sys/time.h> #ifdef PROTO_HELLO #define HELLO_TIMER_UPDATE 0 #define HELLO_TIMER_FLASH 1 static task *hello_task = (task *) 0; static time_t hello_next_flash = (time_t) 0; int hello_pointopoint = FALSE; /* Are we ONLY doing pointopoint HELLO? */ int hello_supplier = -1; /* Are we broadcasting HELLO protocols? */ int doing_hello = FALSE; /* Are we running HELLO protocols? */ metric_t hello_default_metric; /* Default metric to use when propogating */ pref_t hello_preference; /* Preference for HELLO routes */ int hello_n_trusted = 0; /* Number of trusted gateways */ int hello_n_source = 0; /* Number of source gateways */ gw_entry *hello_gw_list = NULL; /* List of HELLO gateways */ adv_entry *hello_accept_list = NULL; /* List of nets to accept from HELLO */ adv_entry *hello_propagate_list = NULL; /* LIst of sources to propagates routes to HELLO */ adv_entry **hello_int_accept = NULL; /* List of accept lists per interface */ adv_entry **hello_int_propagate = NULL; /* List of propagate lists per interface */ metric_t hop_to_hello[] = { /* Translate interface metric to hello metric */ 0, /* 0 */ 100, /* 1 */ 148, /* 2 */ 219, /* 3 */ 325, /* 4 */ 481, /* 5 */ 713, /* 6 */ 1057, /* 7 */ 1567, /* 8 */ 2322, /* 9 */ 3440, /* 10 */ 5097, /* 11 */ 7552, /* 12 */ 11190, /* 13 */ 16579, /* 14 */ 24564, /* 15 */ 30000 /* 16 */ }; /* Routines for support of the hello window system */ /* * initialize the sliding HELLO history window. */ static void hello_win_init(hwp, tdelay) struct hello_win *hwp; int tdelay; { int msf = 0; while (msf < HWINSIZE) hwp->h_win[msf++] = DELAY_INFINITY; hwp->h_index = 0; hwp->h_min = tdelay; hwp->h_min_ttl = 0; hwp->h_win[0] = tdelay; } /* * add a HELLO derived time delay to the route entries HELLO window. */ static void hello_win_add(hwp, tdelay) struct hello_win *hwp; int tdelay; { int msf, t_index = 0; hwp->h_index++; if (hwp->h_index >= HWINSIZE) hwp->h_index = 0; hwp->h_win[hwp->h_index] = tdelay; if (tdelay > hwp->h_min) hwp->h_min_ttl++; else { hwp->h_min = tdelay; hwp->h_min_ttl = 0; } if (hwp->h_min_ttl >= HWINSIZE) { hwp->h_min = DELAY_INFINITY; for (msf = 0; msf < HWINSIZE; msf++) if (hwp->h_win[msf] <= hwp->h_min) { hwp->h_min = hwp->h_win[msf]; t_index = msf; } hwp->h_min_ttl = 0; if (t_index < hwp->h_index) hwp->h_min_ttl = hwp->h_index - t_index; else if (t_index > hwp->h_index) hwp->h_min_ttl = HWINSIZE - (t_index - hwp->h_index); } } /* * Dump info about a HELLO route */ static void hello_rt_dump(fd, rt) FILE *fd; rt_entry *rt; { int cnt, ind; struct hello_win *hwp = (struct hello_win *) rt->rt_data->rtd_data; (void) fprintf(fd, "\t\t\tMinimum HELLO time delay in last %d updates: %d\n", HWINSIZE, hwp->h_min); (void) fprintf(fd, "\tLast %d HELLO time delays:\n\t\t", HELLO_REPORT); ind = hwp->h_index; for (cnt = HELLO_REPORT; cnt; cnt--) { (void) fprintf(fd, "%d ", hwp->h_win[ind]); if (++ind >= HWINSIZE) { ind = 0; } } (void) fprintf(fd, "\n"); } /* * Trace a HELLO packet */ /* ARGSUSED */ static void hello_trace(comment, src, dst, hello, length, nets) char *comment; struct sockaddr_in *src, *dst; char *hello; int length, nets; { int i; const char *cp; char *end = hello + length; struct hm_hdr hm_hdr; struct hellohdr hellohdr; struct type0pair type0pair; struct type1pair type1pair; struct iovec iov; tracef("HELLO %s %A -> %A %d bytes", comment, src, dst, length); if (nets >= 0) { tracef(" %d nets", nets); } /* Calculate the checksum of this packet */ iov.iov_base = hello; iov.iov_len = length; if (gd_inet_cksum(&iov, 1, length)) { tracef(" *checksum bad*"); } trace(TR_HELLO, 0, NULL); PickUp_hellohdr(hello, hellohdr); if (trace_flags & TR_UPDATE) { switch (hellohdr.h_date & H_DATE_BITS) { case H_DATE_LEAPADD: cp = "add_leap_second "; break; case H_DATE_LEAPDEL: cp = "del_leap_second "; break; case H_DATE_UNSYNC: cp = "unsync "; break; default: cp = ""; } hellohdr.h_date &= ~H_DATE_BITS; trace(TR_NOSTAMP | TR_HELLO, 0, "%s %s%d/%d/%d %02d:%02d:%02d.%03d GMT tstp %d", comment, cp, (hellohdr.h_date >> H_DATE_MON_SHIFT) & H_DATE_MON_MASK, (hellohdr.h_date >> H_DATE_DAY_SHIFT) & H_DATE_DAY_MASK, ((hellohdr.h_date >> H_DATE_YEAR_SHIFT) & H_DATE_YEAR_MASK) + H_DATE_YEAR_BASE, hellohdr.h_time / (60 * 60 * 1000), (hellohdr.h_time / (60 * 1000)) % 60, (hellohdr.h_time / (1000)) % 60, hellohdr.h_time % 1000, hellohdr.h_tstp); while (hello < end) { PickUp_hm_hdr(hello, hm_hdr); trace(TR_NOSTAMP | TR_HELLO, 0, "%s\ttype %d count %d", comment, hm_hdr.hm_type, hm_hdr.hm_count); for (i = 0; i < hm_hdr.hm_count; i++) { switch (hm_hdr.hm_type) { case 0: PickUp_type0pair(hello, type0pair); trace(TR_NOSTAMP | TR_HELLO, 0, "%s\t\tdelay %d offset %d", comment, type0pair.d0_delay, type0pair.d0_offset); break; case 1: PickUp_type1pair(hello, type1pair); trace(TR_NOSTAMP | TR_HELLO, 0, "%s\t\t%-15s delay %5d offset %d", comment, inet_ntoa(type1pair.d1_dst), type1pair.d1_delay, type1pair.d1_offset); break; default: trace(TR_NOSTAMP | TR_HELLO, 0, "%s\t\tInvalid type - giving up!", comment); return; } } } trace(TR_HELLO, 0, NULL); } } /* * hello_send(): * Fill in the hello header and checksum, then send the packet. */ static void hello_send(tp, dst, src, flags, iov, length, n_nets) task *tp; struct sockaddr_in *dst, *src; flag_t flags; struct iovec *iov; int length; /* length in octets of hello packet */ int n_nets; /* number of nets in this update for debugging */ { char *hello = iov->iov_base; struct hellohdr hellohdr; struct tm *gmt; struct timeval timep; int error = FALSE; (void) gettimeofday(&timep, (struct timezone *) 0); gmt = (struct tm *) gmtime(&timep.tv_sec); /* * set the date field in the HELLO header. Be very careful here as * the last two bits (14&15) should be set so the Fuzzware doesn't use * this packet to synchronize its Master Clock. Using bitwise OR's * instead of addition just to be safe when dealing with h_date which * is an unsigned short. */ hellohdr.h_date = ((gmt->tm_year - H_DATE_YEAR_BASE) & H_DATE_YEAR_MASK) | ((gmt->tm_mday & H_DATE_DAY_MASK) << H_DATE_DAY_SHIFT) | (((gmt->tm_mon + 1) & H_DATE_MON_MASK) << H_DATE_MON_SHIFT) | H_DATE_UNSYNC; /* * milliseconds since midnight UT of current day */ hellohdr.h_time = (gmt->tm_sec + gmt->tm_min * 60 + gmt->tm_hour * 3600) * 1000 + timep.tv_usec / 1000; /* * 16 bit field used in rt calculation, 0 for ethernets */ hellohdr.h_tstp = 0; hellohdr.h_cksum = 0; PutDown_hellohdr(hello, hellohdr); hellohdr.h_cksum = gd_inet_cksum(iov, 1, length); hello = iov->iov_base; PutDown(hello, hellohdr.h_cksum); if (task_send_packet(tp, iov->iov_base, length, flags, (sockaddr_un *) dst) < 0) { error = TRUE; } TRACE_HELLOPKT(error ? "*NOT* SENT" : "SENT", src, dst, iov->iov_base, length, n_nets); return; } /* * Process an incomming HELLO packet */ static void hello_recv(tp) task *tp; { int count; int i; flag_t rte_table; char *hello, *end; struct hm_hdr hm_hdr; struct type1pair type1pair; rt_entry *rt; if_entry *ifp, *ifpc; gw_entry *gwp; pref_t preference; struct sockaddr_in src; struct sockaddr_in dst; if (task_receive_packet(tp, &count)) { return; } hello = (char *) recv_iovec[RECV_IOVEC_DATA].iov_base; end = hello + recv_ip.ip_len; sockclear_in(&src); sockclear_in(&dst); src.sin_addr = recv_ip.ip_src; /* struct copy */ dst.sin_addr = recv_ip.ip_dst; /* struct copy */ TRACE_HELLOPKT("RECV", &src, &dst, hello, recv_ip.ip_len, -1); /* Locate or create a gateway structure for this gateway */ gwp = gw_timestamp(&hello_gw_list, hello_task->task_rtproto, (sockaddr_un *) & recv_addr); /* If we have a list of trusted gateways, verify that this gateway is trusted */ if (hello_n_trusted && !(gwp->gw_flags & GWF_TRUSTED)) { return; } /* Do we share a net with the sender? */ if ((ifp = if_withdst((sockaddr_un *) & recv_addr)) == NULL) { trace(TR_EXT, LOG_WARNING, "hello_recv: gw %A no shared net?", &recv_addr); return; } if (ifp->int_state & IFS_NOHELLOIN) { return; } /* * Are we talking to ourselves? * * if_withaddr() handles PTP links also. If packet came * from other end of a PTP, let it fall through for further * processing. We shouldn't ever hear our own HELLOs on a PTP link. */ ifpc = if_withaddr((sockaddr_un *) & recv_addr); if (ifpc) { if_rtupdate(ifpc); if ((ifpc->int_state & IFS_POINTOPOINT) == 0) { return; } } /* * update the interface timer on interface the packet came in on. */ if_rtupdate(ifp); gwp = gw_timestamp(&hello_gw_list, hello_task->task_rtproto, (sockaddr_un *) & recv_addr); /* check the hello checksum */ if (gd_inet_cksum(&recv_iovec[RECV_IOVEC_DATA], 1, recv_ip.ip_len) != (u_short) 0) { trace(TR_HELLO, LOG_WARNING, "hello_recv: bad HELLO checksum from %A", &recv_addr); return; } /* message is made up of one or more sub messages */ rt_open(tp); hello += Size_hellohdr; while (hello < end) { PickUp_hm_hdr(hello, hm_hdr); switch (hm_hdr.hm_type) { case 0: hello += Size_type0pair * hm_hdr.hm_count; /* not interested in type 0 messages */ break; case 1: for (i = 0; i < hm_hdr.hm_count; i++) { preference = hello_preference; PickUp_type1pair(hello, type1pair); sockclear_in(&dst); dst.sin_addr = type1pair.d1_dst; /* is this new net acceptable? */ if (!is_valid_in((sockaddr_un *) & dst, hello_accept_list, INT_CONTROL(hello_int_accept, ifp), gwp->gw_accept, &preference)) { continue; } /* Force delay to be valid */ if (type1pair.d1_delay > DELAY_INFINITY) { type1pair.d1_delay = DELAY_INFINITY; } /* * Add the interface metric converted to a HELLO delay. */ type1pair.d1_delay += hop_to_hello[ifp->int_metric] + HELLO_DELAY; /* Determine routing table based on host bits */ rte_table = gd_inet_ishost(&dst) ? RTS_HOSTROUTE : RTS_INTERIOR; /* check for internal route */ rt = rt_locate(rte_table, (sockaddr_un *) & dst, tp->task_rtproto); if (!rt) { /* new route */ if (type1pair.d1_delay >= DELAY_INFINITY) { continue; } rt = rt_add((sockaddr_un *) & dst, (sockaddr_un *) 0, (sockaddr_un *) & recv_addr, gwp, (metric_t) type1pair.d1_delay, rte_table, hello_task->task_rtproto, 0, (time_t) 0, preference); if (rt) { rt->rt_data = rtd_alloc(sizeof(struct hello_win)); rt->rt_data->rtd_dump = hello_rt_dump; hello_win_init((struct hello_win *) rt->rt_data->rtd_data, (metric_t) type1pair.d1_delay); } } else { /* update existing route */ if (type1pair.d1_delay >= DELAY_INFINITY) { /* destination now unreachable */ if (equal(&rt->rt_router, &recv_addr)) { (void) rt_unreach(rt); hello_win_add((struct hello_win *) rt->rt_data->rtd_data, DELAY_INFINITY); } continue; } if (equal(&rt->rt_router, &recv_addr)) { if ((METRIC_DIFF(rt->rt_metric, type1pair.d1_delay) >= HELLO_HYST(rt->rt_metric)) || (rt->rt_state & RTS_HOLDDOWN)) { if (rt_change(rt, (sockaddr_un *) & recv_addr, (metric_t) type1pair.d1_delay, (time_t) 0, preference)) { hello_win_add((struct hello_win *) rt->rt_data->rtd_data, (metric_t) type1pair.d1_delay); } } rt_refresh(rt); } else { if (rt->rt_state & RTS_HOLDDOWN) { continue; } /* * use the new gateway. */ if (((type1pair.d1_delay < rt->rt_metric) && (METRIC_DIFF(type1pair.d1_delay, rt->rt_metric) >= HELLO_HYST(rt->rt_metric))) || (rt->rt_timer > rt->rt_timer_max / 2 && !(rt->rt_state & (RTS_CHANGED | RTS_REFRESH)))) { if (rt_change(rt, (sockaddr_un *) & recv_addr, (metric_t) type1pair.d1_delay, (time_t) 0, hello_preference)) { hello_win_init((struct hello_win *) rt->rt_data->rtd_data, (metric_t) type1pair.d1_delay); } } } } } /* for each advertized net */ break; default: trace(TR_INT, LOG_ERR, "hello_recv: invalid type %d", hm_hdr.hm_type); } /* switch (mh->hm_type) */ } /* while not end of packet */ if (rt_close(tp, gwp, (int) hm_hdr.hm_count)) { task_flash(tp); } } /*ARGSUSED*/ static void hello_supply(tp, dst, src, ifp, gwp, do_split_horizon, flash_update) task *tp; struct sockaddr_in *dst, *src; if_entry *ifp; gw_entry *gwp; int do_split_horizon; int flash_update; { int length; char *hello; char *save_ptr, *hm_hdr_ptr; rt_entry *rt; struct hm_hdr hm_hdr; struct type1pair type1pair; metric_t delay = 0, split_horizon; struct iovec *iovec = &recv_iovec[RECV_IOVEC_DATA]; /* Share receive buffer */ hello = iovec->iov_base + Size_hellohdr; hm_hdr_ptr = hello; hello += Size_hm_hdr; save_ptr = hello; hm_hdr.hm_type = 1; hm_hdr.hm_count = 0; RT_TABLE(rt) { if (rt->rt_state & RTS_NOADVISE) { continue; } if (flash_update && (hello_task->task_rtrevision >= rt->rt_revision)) { continue; } /* Do not send interface routes back to the same interface */ if ((rt->rt_ifp == ifp) && (rt->rt_proto & RTPROTO_DIRECT)) { continue; } /* Subnets and host routes do not go everywhere */ if (rt->rt_state & RTS_HOSTROUTE) { if (((ifp->int_net.in.sin_addr.s_addr ^ rt->rt_dest.in.sin_addr.s_addr) & ifp->int_netmask.in.sin_addr.s_addr) && !((rt->rt_ifp->int_net.in.sin_addr.s_addr ^ rt->rt_dest.in.sin_addr.s_addr) & rt->rt_ifp->int_netmask.in.sin_addr.s_addr)) { /* Host is being sent to another network and we learned it via it's home network */ /* XXX - This assumes we are announcing the network route */ continue; } } else if (rt->rt_state & RTS_SUBNET) { if ((rt->rt_dest.in.sin_addr.s_addr & ifp->int_netmask.in.sin_addr.s_addr) != ifp->int_net.in.sin_addr.s_addr) { /* Only send subnets to interfaces of the same network */ continue; } } else { if (rt->rt_dest.in.sin_addr.s_addr == ifp->int_net.in.sin_addr.s_addr) { /* Do not send the whole net to a subnet */ continue; } } /* XXX - is this adequate? */ if ((rt->rt_proto & hello_task->task_rtproto) && (ifp == rt->rt_ifp)) { split_horizon = DELAY_INFINITY; } else { split_horizon = 0; } if (rt->rt_ifp->int_state & IFS_LOOPBACK) { /* Routes via the loopback interface must have an explicit metric */ delay = DELAY_INFINITY; } delay = (rt->rt_proto & RTPROTO_DIRECT) ? HELLO_DELAY : hello_default_metric; if (!propagate(rt, hello_task->task_rtproto, hello_propagate_list, INT_CONTROL(hello_int_propagate, ifp), gwp ? gwp->gw_propagate : NULL, &delay)) { continue; } delay += hop_to_hello[ifp->int_metric]; if (delay > DELAY_INFINITY) { delay = DELAY_INFINITY; } if (split_horizon) { delay = split_horizon; } if (!(rt->rt_ifp->int_state & IFS_UP) || (rt->rt_state & (RTS_HOLDDOWN | RTS_DELETE))) { delay = DELAY_INFINITY; } if (flash_update && (delay == DELAY_INFINITY) && (rt->rt_ifp == ifp) && (rt->rt_proto & hello_task->task_rtproto)) { /* Don't flash deleted or unreachable routes back to their source */ continue; } if ((hello + Size_type1pair - iovec->iov_base) >= HELLOMAXPACKETSIZE) { /* XXX - fragments should be rate limited to one every 0.5-2.0 seconds */ /* XXX - Maybe HELLO should have a random timer running all the time */ length = hello - iovec->iov_base; hello = hm_hdr_ptr; PutDown_hm_hdr(hello, hm_hdr); hello_send(tp, dst, src, 0, iovec, length, (int) hm_hdr.hm_count); hello = save_ptr; hm_hdr.hm_count = 0; } type1pair.d1_delay = delay; type1pair.d1_offset = 0; /* should be signed clock offset */ type1pair.d1_dst = rt->rt_dest.in.sin_addr; /* struct copy */ PutDown_type1pair(hello, type1pair); hm_hdr.hm_count++; } RT_TABLEEND; if (hm_hdr.hm_count) { length = hello - iovec->iov_base; PutDown_hm_hdr(hm_hdr_ptr, hm_hdr); hello_send(tp, dst, src, 0, iovec, length, (int) hm_hdr.hm_count); } } /* * call hello_supply to supply hello packets to all our nets */ /*ARGSUSED*/ static void hello_job(tip, interval) timer *tip; time_t interval; { task_toall(tip->timer_task, hello_supply, hello_pointopoint, IFS_NOHELLOOUT, hello_n_source ? hello_gw_list : NULL, FALSE); } /* * send a flash update packet */ /*ARGSUSED*/ static void hello_do_flash(tip, interval) timer *tip; time_t interval; { trace(TR_TASK, 0, "hello_do_flash: Doing flash update for HELLO"); task_toall(hello_task, hello_supply, hello_pointopoint, IFS_NOHELLOOUT, hello_n_source ? hello_gw_list : NULL, TRUE); hello_next_flash = (time_t) 2 + time_sec; trace(TR_TASK, 0, "hello_do_flash: Flash update done, none before %T", hello_next_flash); } /* * Check to see if a flash update packet is allowed and send or schedule it */ static void hello_flash(tp) task *tp; { if (time_sec >= hello_next_flash) { /* A flash update can be sent now, do it */ hello_do_flash(tp->task_timer[HELLO_TIMER_FLASH], (time_t) 0); } else if (!tp->task_timer[HELLO_TIMER_FLASH] && (tp->task_timer[HELLO_TIMER_UPDATE]->timer_next_time > hello_next_flash)) { /* A flash update can't be sent and one is not yet scheduled */ (void) timer_create(tp, HELLO_TIMER_FLASH, "Flash", TIMERF_DELETE | TIMERF_ABSOLUTE, hello_next_flash - time_sec, hello_do_flash); } } /* * Cleanup before re-init */ /*ARGSUSED*/ static void hello_cleanup(tp) task *tp; { adv_cleanup(&hello_n_trusted, &hello_n_source, hello_gw_list, &hello_accept_list, &hello_propagate_list, &hello_int_accept, &hello_int_propagate); } /* * Dump info about HELLO */ static void hello_dump(fd) FILE *fd; { (void) fprintf(fd, "HELLO:\n"); (void) fprintf(fd, "\tDefault metric: %d\t\tDefault preference: %d\n", hello_default_metric, hello_preference); if (hello_gw_list) { (void) fprintf(fd, "\tActive gateways:\n"); gw_dump(fd, "\t\t", hello_gw_list); } control_accept_dump(fd, 1, hello_accept_list, hello_int_accept, hello_gw_list); control_propagate_dump(fd, 1, hello_propagate_list, hello_int_propagate, hello_gw_list); (void) fprintf(fd, "\n\n"); } /* * Initialize HELLO socket and task */ /*ARGSUSED*/ void hello_init() { int hello_socket = 1; if_entry *ifp; void (*flash) () = hello_flash; /* Hack for UTX/32 and Ultrix */ if (doing_hello) { if (!hello_task) { if (hello_supplier < 0) { if (n_interfaces > 1) { hello_supplier = TRUE; trace(TR_ALL, LOG_NOTICE, "hello_init: Acting as HELLO supplier to our direct nets"); } IF_LIST(ifp) { if (ifp->int_state & IFS_POINTOPOINT) { hello_supplier = TRUE; trace(TR_INT, 0, "init_hello: PointoPoint HELLO supplier to: %s", ifp->int_name); } } IF_LISTEND(ifp) ; } if (hello_supplier < 0) { hello_supplier = FALSE; } if ((hello_socket = task_get_socket(AF_INET, SOCK_RAW, IPPROTO_HELLO)) < 0) { quit(errno); } hello_task = task_alloc("HELLO"); hello_task->task_flags = TASKF_IPHEADER; hello_task->task_proto = IPPROTO_HELLO; hello_task->task_socket = hello_socket; hello_task->task_rtproto = RTPROTO_HELLO; hello_task->task_recv = hello_recv; hello_task->task_cleanup = hello_cleanup; hello_task->task_dump = hello_dump; if (hello_supplier) { hello_task->task_flash = flash; (void) timer_create(hello_task, HELLO_TIMER_UPDATE, "Update", 0, (time_t) HELLO_TIMERRATE, hello_job); if (task_set_option(hello_task, TASKOPTION_RECVBUF, (caddr_t) (16 * 1024)) < 0) { quit(errno); } if (task_set_option(hello_task, TASKOPTION_DONTROUTE, (caddr_t) TRUE) < 0) { quit(errno); } } if (!task_create(hello_task, HELLOMAXPACKETSIZE)) { quit(EINVAL); } if (HELLO_TIMERRATE < rt_timer->timer_interval) { timer_interval(rt_timer, (time_t) HELLO_TIMERRATE); } } if (hello_supplier) { if_rtactive = TRUE; /* Indicate we are broadcasting */ ignore_redirects = TRUE; /* Gateways don't listen to redirects */ } } else { hello_cleanup((task *) 0); if (hello_task) { task_delete(hello_task); hello_task = (task *) 0; } } } #endif /* PROTO_HELLO */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.