📄 inet.c
字号:
STATIC voidss_socket_put(struct socket *sock){ struct sock *sk; ensure(sock, return); if ((sk = sock->sk)) { /* We don't really need to lock out interrupts here, just bottom halves 'cause a read lock is taken in the callback function itself. */ write_lock_bh(&sk->callback_lock); { ss_t *ss; if ((ss = SOCK_PRIV(sk))) { SOCK_PRIV(sk) = NULL; ss->refcnt--; sk->state_change = ss->cb_save.state_change; sk->data_ready = ss->cb_save.data_ready; sk->write_space = ss->cb_save.write_space; sk->error_report = ss->cb_save.error_report; } else assure(ss); } write_unlock_bh(&sock->sk->callback_lock); /* The following will cause the socket to be aborted, particularly for Linux TCP or other orderly release sockets. XXX: Perhaps should check the state of the socket and call sk->prot->disconnect() first as well. SCTP will probably behave better that way. */ sk->linger = 1; sk->lingertime = 0; } else assure(sk); sock_release(sock);}STATIC voidss_socket_get(struct socket *sock, ss_t * ss){ struct sock *sk; ensure(sock, return); if ((sk = sock->sk)) { /* We don't really need to lock out interrupts here, just bottom halves 'cause a read lock is taken in the callback function itself. */ write_lock_bh(&sock->sk->callback_lock); { SOCK_PRIV(sk) = ss; ss->refcnt++; ss->cb_save.state_change = sk->state_change; ss->cb_save.data_ready = sk->data_ready; ss->cb_save.write_space = sk->write_space; ss->cb_save.error_report = sk->error_report; sk->state_change = ss_state_change; sk->data_ready = ss_data_ready; sk->write_space = ss_write_space; sk->error_report = ss_error_report;#ifdef LINUX_2_4 sk->protinfo.af_inet.recverr = 1;#else sk->ip_recverr = 1;#endif ss->tcp_state = sk->state; /* initialized tcp state */ } write_unlock_bh(&sock->sk->callback_lock); } else assure(sk);}/* * ========================================================================= * * Locking * * ========================================================================= */STATIC intss_trylockq(queue_t *q){ int res; ss_t *ss = PRIV(q); spin_lock_bh(&ss->qlock); if (!(res = !ss->users++)) { if (q == ss->rq) ss->rwait = q; if (q == ss->wq) ss->wwait = q; } spin_unlock_bh(&ss->qlock); return (res);}STATIC voidss_unlockq(queue_t *q){ ss_t *ss = PRIV(q); spin_lock_bh(&ss->qlock); if (ss->rwait) qenable(xchg(&ss->rwait, NULL)); if (ss->wwait) qenable(xchg(&ss->wwait, NULL)); ss->users = 0; spin_unlock_bh(&ss->qlock);}/* * ========================================================================= * * Buffer Allocation * * ========================================================================= *//* * BUFSRV calls service routine * ------------------------------------------------------------------------- */STATIC voidss_bufsrv(long data){ queue_t *q = (queue_t *) data; if (q) { ss_t *ss = PRIV(q); spin_lock_bh(&ss->lock); if (q == ss->rq) { if (ss->rbid) { ss->rbid = 0; ss->refcnt--; } } else if (q == ss->wq) { if (ss->wbid) { ss->wbid = 0; ss->refcnt--; } } else swerr(); spin_unlock_bh(&ss->lock); qenable(q); }}/* * UNBUFCALL * ------------------------------------------------------------------------- */STATIC void__ss_unbufcall(queue_t *q){ ss_t *ss = PRIV(q); if (ss->rbid) { unbufcall(xchg(&ss->rbid, 0)); ss->refcnt--; } if (ss->wbid) { unbufcall(xchg(&ss->wbid, 0)); ss->refcnt--; }}/* * ALLOCB * ------------------------------------------------------------------------- */STATIC mblk_t *ss_allocb(queue_t *q, size_t size, int prior){ mblk_t *mp; if ((mp = allocb(size, prior))) return (mp); else { ss_t *ss = PRIV(q); spin_lock_bh(&ss->lock); if (q == ss->rq) { if (!ss->rbid) { ss->rbid = bufcall(size, prior, &ss_bufsrv, (long) q); ss->refcnt++; } } else if (q == ss->wq) { if (!ss->wbid) { ss->wbid = bufcall(size, prior, &ss_bufsrv, (long) q); ss->refcnt++; } } else swerr(); spin_unlock_bh(&ss->lock); return (NULL); }}#if 0/* * ESBALLOC * ------------------------------------------------------------------------- */STATIC mblk_t *ss_esballoc(queue_t *q, unsigned char *base, size_t size, int prior, frtn_t *frtn){ mblk_t *mp; if ((mp = esballoc(base, size, prior, frtn))) return (mp); else { ss_t *ss = PRIV(q); if (q == ss->rq) { if (!ss->rbid) { ss->rbid = esbbcall(prior, &ss_bufsrv, (long) q); ss->refcnt++; } return (NULL); } if (q == ss->wq) { if (!ss->wbid) { ss->wbid = esbbcall(prior, &ss_bufsrv, (long) q); ss->refcnt++; } return (NULL); } swerr(); return (NULL); }}#endif/* * ========================================================================= * * OPTION Handling * * ========================================================================= */#define T_SPACE(len) \ (sizeof(struct t_opthdr) + T_ALIGN(len))#define T_LENGTH(len) \ (sizeof(struct t_opthdr) + len)#define _T_SPACE_SIZEOF(s) \ T_SPACE(sizeof(s))#define _T_LENGTH_SIZEOF(s) \ T_LENGTH(sizeof(s))STATIC ss_options_t ss_defaults = { {0,} , { xti_default_debug, xti_default_linger, xti_default_rcvbuf, xti_default_rcvlowat, xti_default_sndbuf, xti_default_sndlowat, } , { ip_default_options, ip_default_tos, ip_default_ttl, ip_default_reuseaddr, ip_default_dontroute, ip_default_broadcast, } , { udp_default_checksum, } , { tcp_default_nodelay, tcp_default_maxseg, tcp_default_keepalive, }#if defined HAVE_OPENSS7_SCTP , { sctp_default_nodelay, sctp_default_maxseg, sctp_default_cork, sctp_default_ppi, sctp_default_sid, sctp_default_ssn, sctp_default_tsn, sctp_default_recvopt, sctp_default_cookie_life, sctp_default_sack_delay, sctp_default_path_max_retrans, sctp_default_assoc_max_retrans, sctp_default_max_init_retries, sctp_default_heartbeat_itvl, sctp_default_rto_initial, sctp_default_rto_min, sctp_default_rto_max, sctp_default_ostreams, sctp_default_istreams, sctp_default_cookie_inc, sctp_default_throttle_itvl, sctp_default_mac_type, sctp_default_cksum_type, sctp_default_hb, sctp_default_rto, sctp_default_status, sctp_default_debug,#if defined CONFIG_SCTP_ECN sctp_default_ecn,#endif#if defined CONFIG_SCTP_ADD_IP || defined CONFIG_SCTP_ADAPTATION_LAYER_INFO sctp_default_ali,#endif#if defined CONFIG_SCTP_ADD_IP sctp_default_add, sctp_default_set, sctp_default_add_ip, sctp_default_del_ip, sctp_default_set_ip,#endif#if defined CONFIG_SCTP_PARTIAL_RELIABILITY sctp_default_pr,#endif#if defined CONFIG_SCTP_LIFETIMES || defined CONFIG_SCTP_PARTIAL_RELIABILITY sctp_default_lifetime,#endif sctp_default_disposition, sctp_default_max_burst, }#endif /* defined HAVE_OPENSS7_SCTP */};/* * Size connection indication or confirmation options. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Return an option buffer size for a connection indication or confirmation. * Options without end-to-end significance are not indicated and are only * confirmed if requested. Options with end-to-end significance are always * both indicated and confirmed. For this to work for connection * indications, all request options flags must be cleared to zero. */STATIC intss_size_conn_opts(ss_t * ss){ int size = 0; if (ss_tst_bit(_T_BIT_XTI_DEBUG, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.debug); if (ss_tst_bit(_T_BIT_XTI_LINGER, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.linger); if (ss_tst_bit(_T_BIT_XTI_RCVBUF, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.rcvbuf); if (ss_tst_bit(_T_BIT_XTI_RCVLOWAT, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.rcvlowat); if (ss_tst_bit(_T_BIT_XTI_SNDBUF, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.sndbuf); if (ss_tst_bit(_T_BIT_XTI_SNDLOWAT, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.xti.sndlowat); if (ss->p.prot.family == PF_INET) { { /* These two have end-to-end significance for connection indications and responses. */ // if (ss_tst_bit(_T_BIT_IP_OPTIONS, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.options); // if (ss_tst_bit(_T_BIT_IP_TOS, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.tos); } if (ss_tst_bit(_T_BIT_IP_TTL, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.ttl); if (ss_tst_bit(_T_BIT_IP_REUSEADDR, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.reuseaddr); if (ss_tst_bit(_T_BIT_IP_DONTROUTE, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.dontroute); if (ss_tst_bit(_T_BIT_IP_BROADCAST, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.broadcast); if (ss_tst_bit(_T_BIT_IP_ADDR, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.ip.addr); switch (ss->p.prot.protocol) { case T_INET_TCP: if (ss_tst_bit(_T_BIT_TCP_NODELAY, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.nodelay); if (ss_tst_bit(_T_BIT_TCP_MAXSEG, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.maxseg); if (ss_tst_bit(_T_BIT_TCP_KEEPALIVE, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.keepalive); if (ss_tst_bit(_T_BIT_TCP_CORK, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.cork); if (ss_tst_bit(_T_BIT_TCP_KEEPIDLE, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.keepidle); if (ss_tst_bit(_T_BIT_TCP_KEEPINTVL, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.keepitvl); if (ss_tst_bit(_T_BIT_TCP_KEEPCNT, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.keepcnt); if (ss_tst_bit(_T_BIT_TCP_SYNCNT, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.syncnt); if (ss_tst_bit(_T_BIT_TCP_LINGER2, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.linger2); if (ss_tst_bit(_T_BIT_TCP_DEFER_ACCEPT, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.defer_accept); if (ss_tst_bit(_T_BIT_TCP_WINDOW_CLAMP, ss->options.flags)) size += _T_SPACE_SIZEOF(ss->options.tcp.window_clamp);#if 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -