This is egp_init.c in view mode; [Download] [Up]
/* * $Header: /disk/d/src/devel/gated/dist/src/RCS/egp_init.c,v 2.1 92/02/24 14:12:31 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. * * * ************************************************************************/ #include "include.h" #include "egp.h" #ifdef PROTO_EGP int egp_neighbors; struct egpngh *egp_neighbor_head; #if defined(AGENT_SNMP) struct egpngh **egp_sort; /* Sorted list of pointers to neighbors */ #endif /* defined(AGENT_SNMP) */ u_short egprid_h; int egp_pktsize; /* EGP max packet size */ pref_t egp_preference; /* Preference for EGP routes */ metric_t egp_default_metric; int doing_egp = FALSE; adv_entry *egp_accept_list = NULL; /* List of EGP advise entries */ adv_entry *egp_propagate_list = NULL; /* List of EGP propagate entries */ u_int egp_reachability[1 << REACH_RATIO]; struct egpstats_t egp_stats = {0, 0, 0, 0}; bits egp_states[] = { {NGS_IDLE, "Idle"}, {NGS_ACQUISITION, "Acquisition"}, {NGS_DOWN, "Down"}, {NGS_UP, "Up"}, {NGS_CEASE, "Cease"}, {-1} }; bits egp_flags[] = { {NGF_SENT_UNSOL, "SentUnsol"}, {NGF_SENT_POLL, "SentPoll"}, {NGF_SENT_REPOLL, "SentRepoll"}, {NGF_RECV_REPOLL, "RecvRepoll"}, {NGF_RECV_UNSOL, "RecvUnsol"}, {NGF_PROC_POLL, "ProcPoll"}, {NGF_DELETE, "Delete"}, {NGF_WAIT, "Wait"}, {NGF_GENDEFAULT, "GenDefault"}, {0, 0} }; bits egp_options[] = { {NGO_METRICOUT, "MetricOut"}, {NGO_ASIN, "AsIn"}, {NGO_ASOUT, "AsOut"}, {NGO_NOGENDEFAULT, "NoGenDefault"}, {NGO_DEFAULTIN, "AcceptDefault"}, {NGO_DEFAULTOUT, "PropagateDefault"}, {NGO_INTERFACE, "Interface"}, {NGO_SADDR, "Saddr"}, {NGO_GATEWAY, "Gateway"}, {NGO_MAXACQUIRE, "MaxAcquire"}, {NGO_VERSION, "Version"}, {NGO_P1, "P1"}, {NGO_P2, "P2"}, {0, 0} }; const char *egp_acq_codes[5] = { "Request", "Confirm", "Refuse", "Cease", "CeaseAck"}; const char *egp_reach_codes[2] = { "Hello", "I-H-U"}; const char *egp_nr_status[3] = { "Indeterminate", "Up", "Down"}; const char *egp_acq_status[8] = { "Unspecified", "ActiveMode", "PassiveMode", "Insufficient Resources", "Prohibited", "Going Down", "Parameter Problem", "Protocol Violation"}; const char *egp_reasons[7] = { "Unspecified", "Bad EGP header format", "Bad EGP data field format", "Reachability info unavailable", "Excessive polling rate", "No response", "Unsupported version"}; #if defined(AGENT_SNMP) /* * Routine to compare to routine table entries, used by egp_init */ int egp_sort_compare(ngp1, ngp2) struct egpngh **ngp1, **ngp2; { u_long dst1 = ntohl((*ngp1)->ng_addr.sin_addr.s_addr); u_long dst2 = ntohl((*ngp2)->ng_addr.sin_addr.s_addr); int compare; if (dst1 < dst2) { compare = -1; } else if (dst1 > dst2) { compare = 1; } else { compare = 0; } return (compare); } void egp_sort_neighbors() { int i; struct egpngh *ngp; /* Build a sorted list of neighbors for network monitoring */ if (egp_sort) { (void) free((caddr_t) egp_sort); } if (egp_neighbors) { egp_sort = (struct egpngh **) calloc((u_int) (egp_neighbors + 1), sizeof(struct egpngh *)); if (!egp_sort) { trace(TR_ALL, LOG_ERR, "egp_sort_neighbors: calloc: %m"); quit(errno); } i = 0; EGP_LIST(ngp) { egp_sort[i++] = ngp; } EGP_LISTEND; qsort((caddr_t) egp_sort, egp_neighbors, sizeof(*egp_sort), egp_sort_compare); } else { egp_sort = (struct egpngh **) 0; } } #endif /* defined(AGENT_SNMP) */ /* * Initialize the reachability structure */ void egp_init_reachability() { int reach, mask, bit, n_bits; for (reach = 0; reach < 1 << REACH_RATIO; reach++) { n_bits = 0; for (bit = 0; bit < REACH_RATIO; bit++) { mask = 1 << bit; if (reach & mask) { n_bits++; } } egp_reachability[reach] = n_bits; } } /* * Terminate signal received for a task */ static void egp_ngp_terminate(tp) task *tp; { struct egpngh *ngp = (struct egpngh *) tp->task_data; ngp->ng_flags |= NGF_DELETE; egp_event_stop(ngp, GODOWN); } /* * Cleanup before re-parse */ static void egp_ngp_cleanup(tp) task *tp; { struct egpngh *ngp = (struct egpngh *) tp->task_data; ngp->ng_flags |= NGF_DELETE; adv_cleanup((int *) 0, (int *) 0, (gw_entry *) 0, &ngp->ng_accept, &ngp->ng_propagate, (adv_entry ***) 0, (adv_entry ***) 0); } /* * Re-init after re-parse */ static void egp_ngp_reinit(tp) task *tp; { struct egpngh *ngp = (struct egpngh *) tp->task_data; if (!doing_egp || (ngp->ng_flags & NGF_DELETE)) { ngp->ng_flags |= NGF_DELETE; egp_event_stop(ngp, GODOWN); } else { switch (ngp->ng_state) { case NGS_IDLE: egp_event_start(tp); break; case NGS_ACQUISITION: case NGS_DOWN: case NGS_UP: case NGS_CEASE: break; } /* Locate our new policy */ if (ngp->ng_asin) { /* If the AS isn't valid now, the correct policy will be located */ /* when the AS becomes valid */ ngp->ng_accept = control_exterior_locate(egp_accept_list, ngp->ng_asin); ngp->ng_propagate = control_exterior_locate(egp_propagate_list, ngp->ng_asin); } } } /* * Cleanup main EGP task before reparse */ /*ARGSUSED*/ static void egp_cleanup(tp) task *tp; { adv_free_list(egp_accept_list); egp_accept_list = (adv_entry *) 0; adv_free_list(egp_propagate_list); egp_propagate_list = (adv_entry *) 0; } /* * Initialize EGP socket and task */ void egp_init() { struct egpngh *ngp; if_entry *ifp; struct sockaddr_in addr; static task *egp_task = (task *) 0; sockclear_in(&addr); if (doing_egp) { if (!egp_task) { egp_task = task_alloc("EGP"); egp_task->task_cleanup = egp_cleanup; egp_task->task_dump = egp_dump; if (!task_create(egp_task, egp_pktsize)) { quit(EINVAL); } } EGP_LIST(ngp) { if (!ngp->ng_task) { /* Check that I have a direct net to neighbor, or if NGO_GATEWAY */ /* is set, that I have a direct net to the specified gateway */ if (!(ngp->ng_options & NGO_INTERFACE)) { if (!(ngp->ng_options & NGO_GATEWAY)) { sockcopy(&ngp->ng_addr, &addr); } else { addr = ngp->ng_gateway; /* struct copy */ } if (ifp = if_withdst((sockaddr_un *) & addr)) { ngp->ng_interface = ifp; } else if (!(ngp->ng_options & NGO_GATEWAY)) { /* If we only have one interface, use it */ ifp = NULL; if (n_interfaces == 1) { IF_LIST(ifp) { if (!(ifp->int_state & IFS_LOOPBACK)) { ngp->ng_interface = ifp; break; } } IF_LISTEND(ifp) ; } if (!ifp) { trace(TR_INT, LOG_ERR, "egp_init: Can't determine interface for neighbor %s", ngp->ng_name); quit(EDESTADDRREQ); } } else { trace(TR_INT, LOG_ERR, "egp_init: no direct net to gateway %s", ngp->ng_name); quit(EDESTADDRREQ); } } /* If ASout is not specified, default to global value */ if (!(ngp->ng_options & NGO_ASOUT)) { ngp->ng_asout = my_system; } if (ngp->ng_options & NGO_ASIN) { ngp->ng_accept = control_exterior_locate(egp_accept_list, ngp->ng_asin); ngp->ng_propagate = control_exterior_locate(egp_propagate_list, ngp->ng_asin); } if (!(ngp->ng_options & NGO_SADDR)) { ngp->ng_saddr.sin_addr = gd_inet_makeaddr(gd_inet_wholenetof(ngp->ng_addr.sin_addr), 0, FALSE); } if (!(ngp->ng_options & NGO_PREFERENCE)) { ngp->ng_preference = egp_preference; } if (!(ngp->ng_options & NGO_P1)) { ngp->ng_P1 = EGP_P1; } if (!(ngp->ng_options & NGO_P2)) { ngp->ng_P2 = EGP_P2; } ngp->ng_state = NGS_IDLE; ngp->ng_V = (ngp->ng_options & NGO_VERSION) ? ngp->ng_version : EGPVER; ngp->ng_S = 1; ngp->ng_T1 = ngp->ng_P1 + HELLOMARGIN; ngp->ng_hello_rate.rate_min = ngp->ng_P1; ngp->ng_poll_rate.rate_min = ngp->ng_P2; ngp->ng_M = ACTIVE; ngp->ng_task = task_alloc("EGP"); ngp->ng_task->task_flags = TASKF_IPHEADER; ngp->ng_task->task_proto = IPPROTO_EGP; ngp->ng_task->task_rtproto = RTPROTO_EGP; sockcopy(&ngp->ng_addr, &ngp->ng_task->task_addr); ngp->ng_task->task_recv = egp_recv; ngp->ng_task->task_data = (caddr_t) ngp; ngp->ng_task->task_terminate = egp_ngp_terminate; ngp->ng_task->task_cleanup = egp_ngp_cleanup; ngp->ng_task->task_reinit = egp_ngp_reinit; /* Allocate a socket for this peer */ if ((ngp->ng_task->task_socket = task_get_socket(AF_INET, SOCK_RAW, IPPROTO_EGP)) < 0) { quit(errno); } if (!task_create(ngp->ng_task, egp_pktsize)) { quit(EINVAL); } /* Set the receive and send buffers so they can hold two max size update packets */ if (task_set_option(ngp->ng_task, TASKOPTION_RECVBUF, (caddr_t) (egp_pktsize * 2)) < 0) { quit(errno); } if (task_set_option(ngp->ng_task, TASKOPTION_SENDBUF, (caddr_t) (egp_pktsize * 2)) < 0) { quit(errno); } if (if_withdst((sockaddr_un *) & ngp->ng_addr) && task_set_option(ngp->ng_task, TASKOPTION_DONTROUTE, (caddr_t) TRUE) < 0) { quit(errno); } if (!test_flag) { /* Set the remote address of the socket */ if (connect(ngp->ng_task->task_socket, (struct sockaddr *) & ngp->ng_addr, socksize(&ngp->ng_addr)) < 0) { trace(TR_ALL, LOG_ERR, "egp_init: connect %A: %m", &addr); quit(errno); } /* Set the local address of the socket */ if (bind(ngp->ng_task->task_socket, (struct sockaddr *) & ngp->ng_interface->int_addr, socksize(&ngp->ng_interface->int_addr)) < 0) { trace(TR_ALL, LOG_ERR, "egp_init: bind %A: %m", &ngp->ng_interface->int_addr); quit(errno); } } (void) timer_create(ngp->ng_task, EGP_TIMER_t1, "t1", 0, (time_t) 0, egp_event_t1); (void) timer_create(ngp->ng_task, EGP_TIMER_t2, "t2", 0, (time_t) 0, egp_event_t2); (void) timer_create(ngp->ng_task, EGP_TIMER_t3, "t3", TIMERF_ABSOLUTE, (ngp->ng_flags & NGF_WAIT) ? (time_t) 0 : (time_t) EGP_START_DELAY, egp_event_t3); } EGP_LISTEND; } egp_init_reachability(); } else { /* Delete any neighbors without tasks */ EGP_LIST(ngp) { if (!ngp->ng_task) { egp_event_delete(ngp); } } EGP_LISTEND; egp_cleanup((task *) 0); if (egp_task) { task_delete(egp_task); egp_task = (task *) 0; } } } #endif /* PROTO_EGP */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.