Changeset 33:e6fcdf12b9a0 in freeDiameter
- Timestamp:
- Oct 29, 2009, 6:05:45 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/CMakeLists.txt
r25 r33 21 21 peers.c 22 22 p_expiry.c 23 p_out.c 23 24 p_psm.c 24 25 server.c -
freeDiameter/config.c
r24 r33 96 96 } else { 97 97 struct fd_list * li = fd_g_config->cnf_endpoints.next; 98 fd_log_debug(" Local endpoints ........ : "); 99 while (li != &fd_g_config->cnf_endpoints) { 100 struct fd_endpoint * ep = (struct fd_endpoint *)li; 101 if (li != fd_g_config->cnf_endpoints.next) fd_log_debug(" "); 102 sSA_DUMP_NODE( &ep->sa, NI_NUMERICHOST ); 103 fd_log_debug("\n"); 104 li = li->next; 105 } 98 fd_log_debug(" Local endpoints ........ : \n"); 99 fd_ep_dump( 29, &fd_g_config->cnf_endpoints ); 106 100 } 107 101 if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) { -
freeDiameter/endpoints.c
r24 r33 109 109 return 0; 110 110 } 111 112 void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep, char * suffix ) 113 { 114 if (prefix) 115 fd_log_debug("%s", prefix); 116 117 sSA_DUMP_NODE_SERV( &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ); 118 fd_log_debug(" {%s%s%s%s}", 119 (ep->flags & EP_FL_CONF) ? "C" : "-", 120 (ep->flags & EP_FL_DISC) ? "D" : "-", 121 (ep->flags & EP_FL_ADV) ? "A" : "-", 122 (ep->flags & EP_FL_LL) ? "L" : "-", 123 (ep->flags & EP_FL_PRIMARY) ? "P" : "-"); 124 if (suffix) 125 fd_log_debug("%s", suffix); 126 } 127 128 void fd_ep_dump( int indent, struct fd_list * eps ) 129 { 130 struct fd_list * li; 131 for (li = eps->next; li != eps; li = li->next) { 132 struct fd_endpoint * ep = (struct fd_endpoint *)li; 133 fd_log_debug("%*s", indent, ""); 134 fd_ep_dump_one( NULL, ep, "\n" ); 135 } 136 } 137 -
freeDiameter/fD.h
r31 r33 42 42 #include <freeDiameter/freeDiameter.h> 43 43 44 #ifdef DISABLE_SCTP 45 #undef IPPROTO_SCTP 46 #define IPPROTO_SCTP (2 = 4) /* some compilation error to spot the references */ 47 #endif /* DISABLE_SCTP */ 48 44 49 /* Timeout for establishing a connection */ 45 50 #ifndef CNX_TIMEOUT … … 102 107 103 108 /* Chaining in peers sublists */ 104 struct fd_list p_actives; /* list of peers in the STATE_OPEN state -- faster routing creation*/109 struct fd_list p_actives; /* list of peers in the STATE_OPEN state -- used by routing */ 105 110 struct fd_list p_expiry; /* list of expiring peers, ordered by their timeout value */ 106 111 struct timespec p_exp_timer; /* Timestamp where the peer will expire; updated each time activity is seen on the peer (except DW) */ … … 124 129 struct timespec p_psm_timer; 125 130 126 /* Received message queue, and thread managing reception of messages */127 struct fifo *p_recv;128 pthread_t p_inthr;129 130 131 /* Outgoing message queue, and thread managing sending the messages */ 131 132 struct fifo *p_tosend; … … 138 139 struct fd_list p_sentreq; 139 140 140 /* connection context: socket , callbacks and soon */141 /* connection context: socket and related information */ 141 142 struct cnxctx *p_cnxctx; 142 143 143 /* Callback on initial connection success / failure */ 144 /* Callback for peer validation after the handshake */ 145 int (*p_cb2)(struct peer_info *); 146 147 /* Callback on initial connection success / failure after the peer was added */ 144 148 void (*p_cb)(struct peer_info *, void *); 145 149 void *p_cb_data; … … 173 177 174 178 }; 179 #define CHECK_PEVENT( _e ) \ 180 (((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) 181 /* The following macro is actually called in p_psm.c -- another solution would be to declare it static inline */ 182 #define DECLARE_PEV_STR() \ 183 const char * fd_pev_str(int event) \ 184 { \ 185 switch (event) { \ 186 case_str(FDEVP_DUMP_ALL); \ 187 case_str(FDEVP_TERMINATE); \ 188 case_str(FDEVP_CNX_MSG_RECV); \ 189 case_str(FDEVP_CNX_ERROR); \ 190 case_str(FDEVP_CNX_EP_CHANGE); \ 191 case_str(FDEVP_CNX_INCOMING); \ 192 case_str(FDEVP_PSM_TIMEOUT); \ 193 } \ 194 TRACE_DEBUG(FULL, "Unknown event : %d", event); \ 195 return "Unknown event"; \ 196 } 175 197 const char * fd_pev_str(int event); 176 #define CHECK_EVENT( _e ) \177 (((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT))178 198 179 199 /* The data structure for FDEVP_CNX_INCOMING events */ … … 211 231 int fd_psm_terminate(struct fd_peer * peer ); 212 232 void fd_psm_abord(struct fd_peer * peer ); 233 234 /* Peer out */ 235 int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer); 236 int fd_out_start(struct fd_peer * peer); 237 int fd_out_stop(struct fd_peer * peer); 238 239 /* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */ 240 extern struct fd_list fd_g_activ_peers; 241 extern pthread_rwlock_t fd_g_activ_peers_rw; /* protect the list */ 242 213 243 214 244 /* Server sockets */ -
freeDiameter/p_psm.c
r29 r33 36 36 #include "fD.h" 37 37 38 const char *peer_state_str[] = { 39 "STATE_NEW" 40 , "STATE_OPEN" 41 , "STATE_CLOSED" 42 , "STATE_CLOSING" 43 , "STATE_WAITCNXACK" 44 , "STATE_WAITCNXACK_ELEC" 45 , "STATE_WAITCEA" 46 , "STATE_OPEN_HANDSHAKE" 47 , "STATE_SUSPECT" 48 , "STATE_REOPEN" 49 , "STATE_ZOMBIE" 50 }; 51 52 const char * fd_pev_str(int event) 53 { 54 switch (event) { 55 #define case_str( _val )\ 56 case _val : return #_val 57 case_str(FDEVP_DUMP_ALL); 58 case_str(FDEVP_TERMINATE); 59 case_str(FDEVP_CNX_MSG_RECV); 60 case_str(FDEVP_CNX_ERROR); 61 case_str(FDEVP_CNX_EP_CHANGE); 62 case_str(FDEVP_CNX_INCOMING); 63 case_str(FDEVP_PSM_TIMEOUT); 64 65 default: 66 TRACE_DEBUG(FULL, "Unknown event : %d", event); 67 return "Unknown event"; 68 } 69 } 70 71 38 /* The actual declaration of peer_state_str */ 39 DECLARE_STATE_STR(); 40 41 /* Helper for next macro */ 42 #define case_str( _val ) \ 43 case _val : return #_val 44 45 DECLARE_PEV_STR(); 46 47 /************************************************************************/ 48 /* Delayed startup */ 49 /************************************************************************/ 72 50 static int started = 0; 73 51 static pthread_mutex_t started_mtx = PTHREAD_MUTEX_INITIALIZER; … … 90 68 } 91 69 92 /* Cancelation cleanup : set ZOMBIE state in the peer */ 93 void cleanup_state(void * arg) 94 { 95 struct fd_peer * peer = (struct fd_peer *)arg; 96 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); 97 peer->p_hdr.info.pi_state = STATE_ZOMBIE; 98 return; 70 /* Allow the state machines to start */ 71 int fd_psm_start() 72 { 73 TRACE_ENTRY(""); 74 CHECK_POSIX( pthread_mutex_lock(&started_mtx) ); 75 started = 1; 76 CHECK_POSIX( pthread_cond_broadcast(&started_cnd) ); 77 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) ); 78 return 0; 79 } 80 81 82 /************************************************************************/ 83 /* Manage the list of active peers */ 84 /************************************************************************/ 85 86 87 /* Enter/leave OPEN state */ 88 static int enter_open_state(struct fd_peer * peer) 89 { 90 CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) ); 91 TODO(" insert in fd_g_activ_peers "); 92 93 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) ); 94 95 /* Start the thread to handle outgoing messages */ 96 CHECK_FCT( fd_out_start(peer) ); 97 98 return ENOTSUP; 99 } 100 static int leave_open_state(struct fd_peer * peer) 101 { 102 TODO("Remove from active list"); 103 104 /* Stop the "out" thread */ 105 CHECK_FCT( fd_out_stop(peer) ); 106 107 TODO("Failover pending messages: requeue in global structures"); 108 109 return ENOTSUP; 110 } 111 112 /************************************************************************/ 113 /* Helpers for state changes */ 114 /************************************************************************/ 115 /* Change state */ 116 static int change_state(struct fd_peer * peer, int new_state) 117 { 118 int old; 119 120 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state)); 121 CHECK_PARAMS( CHECK_PEER(peer) ); 122 old = peer->p_hdr.info.pi_state; 123 if (old == new_state) 124 return 0; 125 126 TRACE_DEBUG(FULL, "'%s'\t-> '%s'\t'%s'", 127 STATE_STR(old), 128 STATE_STR(new_state), 129 peer->p_hdr.info.pi_diamid); 130 131 if (old == STATE_OPEN) { 132 CHECK_FCT( leave_open_state(peer) ); 133 } 134 135 peer->p_hdr.info.pi_state = new_state; 136 137 if (new_state == STATE_OPEN) { 138 CHECK_FCT( enter_open_state(peer) ); 139 } 140 141 return 0; 99 142 } 100 143 … … 128 171 } 129 172 173 174 /************************************************************************/ 175 /* The PSM thread */ 176 /************************************************************************/ 177 /* Cancelation cleanup : set ZOMBIE state in the peer */ 178 void cleanup_state(void * arg) 179 { 180 struct fd_peer * peer = (struct fd_peer *)arg; 181 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); 182 peer->p_hdr.info.pi_state = STATE_ZOMBIE; 183 return; 184 } 185 130 186 /* The state machine thread (controler) */ 131 187 static void * p_psm_th( void * arg ) … … 171 227 /* Now, the action depends on the current state and the incoming event */ 172 228 173 /* The following twostates are impossible */229 /* The following states are impossible */ 174 230 ASSERT( peer->p_hdr.info.pi_state != STATE_NEW ); 175 231 ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE ); 232 ASSERT( peer->p_hdr.info.pi_state != STATE_OPEN_HANDSHAKE ); /* because it exists only between two loops */ 176 233 177 234 /* Purge invalid events */ 178 if (!CHECK_ EVENT(event)) {235 if (!CHECK_PEVENT(event)) { 179 236 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); 180 237 goto psm_loop; 238 } 239 240 /* Call the extension callback if needed */ 241 if (peer->p_cb) { 242 /* Check if we must call it */ 243 /* */ 244 /* OK */ 245 TODO("Call CB"); 246 TODO("Clear CB"); 181 247 } 182 248 … … 207 273 goto psm_loop; 208 274 } 275 } 276 277 /* A message was received */ 278 if (event == FDEVP_CNX_MSG_RECV) { 279 TODO("Parse the buffer into a message"); 280 /* parse_and_get_local_ccode */ 281 TODO("Check if it is a local message (CER, DWR, ...)"); 282 TODO("If not, check we are in OPEN state"); 283 TODO("Update expiry timer if needed"); 284 TODO("Handle the message"); 285 } 286 287 /* The connection object is broken */ 288 if (event == FDEVP_CNX_ERROR) { 289 TODO("Destroy the connection object"); 290 TODO("Mark the error in the peer (pf_cnx_pb)"); 291 TODO("Move to closed state, Requeue all messages to a different connection (failover)"); 292 TODO("If pi_flags.exp, terminate the peer"); 293 } 294 295 /* The connection notified a change in endpoints */ 296 if (event == FDEVP_CNX_EP_CHANGE) { 297 /* Cleanup the remote LL and primary addresses */ 298 CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */); 299 CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */); 300 301 /* Get the new ones */ 302 CHECK_FCT_DO( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); 303 304 if (TRACE_BOOL(ANNOYING)) { 305 fd_log_debug("New remote endpoint(s):\n"); 306 fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); 307 } 308 309 /* Done */ 310 goto psm_loop; 209 311 } 210 312 … … 235 337 } 236 338 237 /* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */ 238 /* If timeout or OPEN : call cb if defined */ 239 240 /* Default action : the handling has not yet been implemented. */ 339 /* The timeout for the current state has been reached */ 340 if (event == FDEVP_PSM_TIMEOUT) { 341 switch (peer->p_hdr.info.pi_state) { 342 343 344 } 345 } 346 347 /* Default action : the handling has not yet been implemented. [for debug only] */ 241 348 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); 242 349 if (event == FDEVP_PSM_TIMEOUT) { … … 252 359 pthread_detach(pthread_self()); 253 360 return NULL; 254 } 255 361 } 362 363 364 /************************************************************************/ 365 /* Functions to control the PSM */ 366 /************************************************************************/ 256 367 /* Create the PSM thread of one peer structure */ 257 368 int fd_psm_begin(struct fd_peer * peer ) … … 283 394 } 284 395 285 /* End the PSM violently*/396 /* End the PSM & cleanup the peer structure */ 286 397 void fd_psm_abord(struct fd_peer * peer ) 287 398 { 288 399 TRACE_ENTRY("%p", peer); 289 400 TODO("Cancel PSM thread"); 290 TODO("Cancel IN thread");291 401 TODO("Cancel OUT thread"); 292 402 TODO("Cleanup the peer connection object"); 293 403 TODO("Cleanup the message queues (requeue)"); 404 TODO("Call p_cb with NULL parameter if needed"); 405 294 406 return; 295 407 } 296 408 297 /* Allow the state machines to start */298 int fd_psm_start()299 {300 TRACE_ENTRY("");301 CHECK_POSIX( pthread_mutex_lock(&started_mtx) );302 started = 1;303 CHECK_POSIX( pthread_cond_broadcast(&started_cnd) );304 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );305 return 0;306 }307 -
freeDiameter/peers.c
r29 r33 40 40 pthread_rwlock_t fd_g_peers_rw = PTHREAD_RWLOCK_INITIALIZER; 41 41 42 /* List of active peers */ 43 struct fd_list fd_g_activ_peers = FD_LIST_INITIALIZER(fd_g_activ_peers); /* peers linked by their p_actives oredered by p_diamid */ 44 pthread_rwlock_t fd_g_activ_peers_rw = PTHREAD_RWLOCK_INITIALIZER; 45 46 /* List of validation callbacks (registered with fd_peer_validate_register) */ 47 static struct fd_list validators = FD_LIST_INITIALIZER(validators); /* list items are simple fd_list with "o" pointing to the callback */ 48 static pthread_rwlock_t validators_rw = PTHREAD_RWLOCK_INITIALIZER; 49 42 50 43 51 /* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */ … … 69 77 p->p_hbh = lrand48(); 70 78 CHECK_FCT( fd_fifo_new(&p->p_events) ); 71 CHECK_FCT( fd_fifo_new(&p->p_recv) );72 79 CHECK_FCT( fd_fifo_new(&p->p_tosend) ); 73 80 fd_list_init(&p->p_sentreq, p); … … 206 213 CHECK_FCT( fd_fifo_del(&p->p_events) ); 207 214 208 CHECK_FCT( fd_thr_term(&p->p_inthr) );209 while ( fd_fifo_tryget(p->p_recv, &t) == 0 ) {210 struct msg * m = t;211 TRACE_DEBUG(FULL, "Found message %p in incoming queue of peer %p being destroyed", m, p);212 /* We simply destroy, the remote peer will re-send to someone else...*/213 CHECK_FCT(fd_msg_free(m));214 }215 CHECK_FCT( fd_fifo_del(&p->p_recv) );216 217 215 CHECK_FCT( fd_thr_term(&p->p_outthr) ); 218 216 while ( fd_fifo_tryget(p->p_tosend, &t) == 0 ) { … … 220 218 TRACE_DEBUG(FULL, "Found message %p in outgoing queue of peer %p being destroyed, requeue", m, p); 221 219 /* We simply requeue in global, the routing thread will re-handle it. */ 222 220 CHECK_FCT(fd_fifo_post(fd_g_outgoing, &m)); 223 221 } 224 222 CHECK_FCT( fd_fifo_del(&p->p_tosend) ); … … 318 316 fd_peer_free(&peer); 319 317 } 318 319 /* Now empty the validators list */ 320 CHECK_FCT_DO( pthread_rwlock_wrlock(&validators_rw), /* continue */ ); 321 while (!FD_IS_LIST_EMPTY( &validators )) { 322 struct fd_list * v = validators.next; 323 fd_list_unlink(v); 324 free(v); 325 } 326 CHECK_FCT_DO( pthread_rwlock_unlock(&validators_rw), /* continue */ ); 320 327 321 328 return 0; … … 460 467 int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) ) 461 468 { 462 463 TODO("..."); 464 return ENOTSUP; 465 } 466 467 /* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error or if the peer is rejected */ 469 struct fd_list * v; 470 471 TRACE_ENTRY("%p", peer_validate); 472 CHECK_PARAMS(peer_validate); 473 474 /* Alloc a new entry */ 475 CHECK_MALLOC( v = malloc(sizeof(struct fd_list)) ); 476 fd_list_init( v, peer_validate ); 477 478 /* Add at the beginning of the list */ 479 CHECK_FCT( pthread_rwlock_wrlock(&validators_rw) ); 480 fd_list_insert_after(&validators, v); 481 CHECK_FCT( pthread_rwlock_unlock(&validators_rw)); 482 483 /* Done! */ 484 return 0; 485 } 486 487 /* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error (>0) or if the peer is rejected (-1) */ 468 488 int fd_peer_validate( struct fd_peer * peer ) 469 489 { 470 TODO("Default to reject"); 471 TODO("Call all callbacks in turn"); 472 TODO("Save cb2 in the peer if needed"); 473 return ENOTSUP; 474 } 490 int ret = 0; 491 struct fd_list * v; 492 493 CHECK_FCT( pthread_rwlock_rdlock(&validators_rw) ); 494 for (v = validators.next; v != &validators; v = v->next) { 495 int auth = 0; 496 pthread_cleanup_push(fd_cleanup_rwlock, &validators_rw); 497 CHECK_FCT_DO( ret = ((int(*)(struct peer_info *, int *, int (**)(struct peer_info *)))(v->o)) (&peer->p_hdr.info, &auth, &peer->p_cb2), goto out ); 498 pthread_cleanup_pop(0); 499 if (auth) { 500 ret = (auth > 0) ? 0 : -1; 501 goto out; 502 } 503 peer->p_cb2 = NULL; 504 } 505 506 /* No callback has given a firm result, the default is to reject */ 507 ret = -1; 508 out: 509 CHECK_FCT( pthread_rwlock_unlock(&validators_rw)); 510 return ret; 511 } -
freeDiameter/sctp.c
r29 r33 49 49 #define SCTP_LEVEL FULL 50 50 #else /* DEBUG_SCTP */ 51 #define SCTP_LEVEL ANNOYING51 #define SCTP_LEVEL (FCTS + 1) 52 52 #endif /* DEBUG_SCTP */ 53 53 -
freeDiameter/server.c
r29 r33 276 276 if (empty_conf_ep) { 277 277 (void) fd_cnx_getendpoints(s->conn, &fd_g_config->cnf_endpoints, NULL); 278 if (TRACE_BOOL(FULL)){ 279 fd_log_debug("Server bound on the following addresses :\n"); 280 fd_ep_dump( 5, &fd_g_config->cnf_endpoints ); 281 } 278 282 } 279 283 -
include/freeDiameter/freeDiameter.h
r25 r33 258 258 #define STATE_MAX STATE_ZOMBIE 259 259 }; 260 extern const char *peer_state_str[]; /* defined in freeDiameter/p_psm.c */ 260 /* The following macro is called in freeDiameter/p_psm.c */ 261 #define DECLARE_STATE_STR() \ 262 const char *peer_state_str[] = { \ 263 "STATE_NEW" \ 264 , "STATE_OPEN" \ 265 , "STATE_CLOSED" \ 266 , "STATE_CLOSING" \ 267 , "STATE_WAITCNXACK" \ 268 , "STATE_WAITCNXACK_ELEC" \ 269 , "STATE_WAITCEA" \ 270 , "STATE_OPEN_HANDSHAKE" \ 271 , "STATE_SUSPECT" \ 272 , "STATE_REOPEN" \ 273 , "STATE_ZOMBIE" \ 274 }; 275 extern const char *peer_state_str[]; 261 276 #define STATE_STR(state) \ 262 277 (((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>") … … 316 331 struct { 317 332 char *priority; /* In case the default priority is not appropriate */ 318 /* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo */333 /* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo see there for example of using this data */ 319 334 const gnutls_datum_t *cert_list; /* The (valid) credentials that the peer has presented */ 320 335 unsigned int cert_list_size;/* Number of certificates in the list */ … … 378 393 * All registered callbacks are called until a callback sets auth = -1 or auth = 1. 379 394 * If no callback returns a clear decision, the default behavior is applied (reject unknown connections) 395 * The callbacks are called in FILO order of their registration. 380 396 * 381 397 * RETURN VALUE: … … 512 528 int fd_ep_filter( struct fd_list * list, uint32_t flags ); 513 529 int fd_ep_clearflags( struct fd_list * list, uint32_t flags ); 514 515 530 void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep, char * suffix ); 531 void fd_ep_dump( int indent, struct fd_list * eps ); 516 532 517 533 #endif /* _FREEDIAMETER_H */ -
include/freeDiameter/libfreeDiameter.h
r29 r33 373 373 374 374 /* A l4 protocol name (TCP / SCTP) */ 375 #ifdef DISABLE_SCTP 376 #define IPPROTO_NAME( _proto ) \ 377 (((_proto) == IPPROTO_TCP) ? "TCP" : \ 378 "Unknown") 379 #else /* DISABLE_SCTP */ 375 380 #define IPPROTO_NAME( _proto ) \ 376 381 ( ((_proto) == IPPROTO_TCP) ? "TCP" : \ 377 382 (((_proto) == IPPROTO_SCTP) ? "SCTP" : \ 378 383 "Unknown")) 384 #endif /* DISABLE_SCTP */ 379 385 380 386 /* The sockaddr length of a sSS structure */
Note: See TracChangeset
for help on using the changeset viewer.