📄 inet.c
字号:
#define TF_SCTP_OSTREAMS (1<<25)#define TF_SCTP_ISTREAMS (1<<26)#define TF_SCTP_COOKIE_INC (1<<27)#define TF_SCTP_THROTTLE_ITVL (1<<28)#define TF_SCTP_MAC_TYPE (1<<29)#define TF_SCTP_HB (1<<30)#define TF_SCTP_RTO (1<<31)#define TF_SCTP_STATUS (1<< 6) /* FIXME */#define TF_SCTP_DEBUG (1<< 7) /* FIXME */#endif#define TM_OPT_SENDMSG ( TF_IP_OPTIONS \ | TF_IP_TOS \ | TF_IP_TTL \ | TF_IP_DONTROUTE \ | TF_IP_PKTINFO \ )#define _T_CHECK 1#define _T_NEGOTIATE 2#define _T_DEFAULT 3#define _T_CURRENT 4#define TF_CHECK (1<<_T_CHECK)#define TF_NEGOTIATE (1<<_T_NEGOTIATE)#define TF_DEFAULT (1<<_T_DEFAULT)#define TF_CURRENT (1<<_T_CURRENT)typedef struct ss_event { struct sock *sk; /* sock (child) for event */ int state; /* state at time of event */} ss_event_t;STATIC lis_spin_lock_t ss_lock; /* protects ss_opens lists */STATIC ss_t *ss_opens = NULL;#if 0/* * for later when we support default destinations and default listeners */STATIC ss_t *ss_dflt_dest = NULL;STATIC ss_t *ss_dflt_lstn = NULL;#endif/* * ========================================================================= * * Socket Callbacks * * ========================================================================= */STATIC void ss_state_change(struct sock *sk);STATIC void ss_write_space(struct sock *sk);STATIC void ss_error_report(struct sock *sk);STATIC void ss_data_ready(struct sock *sk, int len);STATIC voidss_socket_put(struct socket *sock){ struct sock *sk; ensure(sock, return); if ((sk = sock->sk)) { write_lock(&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(&sock->sk->callback_lock); } else assure(sk); sock_release(sock);}STATIC voidss_socket_get(struct socket *sock, ss_t * ss){ struct sock *sk; ensure(sock, return); sk = sock->sk; ensure(sk, return); write_lock(&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(&sock->sk->callback_lock);}/* * ========================================================================= * * Locking * * ========================================================================= */STATIC intss_trylockq(queue_t *q){ int res; ss_t *ss = PRIV(q); if (!(res = lis_spin_trylock(&ss->qlock))) { if (q == ss->rq) ss->rwait = q; if (q == ss->wq) ss->wwait = q; } return (res);}STATIC voidss_unlockq(queue_t *q){ ss_t *ss = PRIV(q); lis_spin_unlock(&ss->qlock); if (ss->rwait) qenable(xchg(&ss->rwait, NULL)); if (ss->wwait) qenable(xchg(&ss->wwait, NULL));}/* * ========================================================================= * * Buffer Allocation * * ========================================================================= *//* * BUFSRV calls service routine * ------------------------------------------------------------------------- */STATIC voidss_bufsrv(long data){ queue_t *q = (queue_t *) data; if (q) { ss_t *ss = PRIV(q); if (q == ss->rq) if (ss->rbid) { ss->rbid = 0; ss->refcnt--; } if (q == ss->wq) if (ss->wbid) { ss->wbid = 0; ss->refcnt--; } qenable(q); }}/* * UNBUFCALL * ------------------------------------------------------------------------- */STATIC voidss_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); if (q == ss->rq) { if (!ss->rbid) { ss->rbid = bufcall(size, prior, &ss_bufsrv, (long) q); ss->refcnt++; } return (NULL); } if (q == ss->wq) { if (!ss->wbid) { ss->wbid = bufcall(size, prior, &ss_bufsrv, (long) q); ss->refcnt++; } return (NULL); } } swerr(); 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_ALIGN_SIZEOF(s) \ ((sizeof((s)) + _T_ALIGN_SIZE - 1) & ~(_T_ALIGN_SIZE - 1))STATIC size_tss_opts_size(ss_t * ss, ss_opts_t * ops){ size_t len = 0; const size_t hlen = sizeof(struct t_opthdr); /* 32 bytes */ if (ops) { if (ops->opt) len += hlen + _T_ALIGN_SIZEOF(*(ops->opt)); if (ops->tos) len += hlen + _T_ALIGN_SIZEOF(*(ops->tos)); if (ops->ttl) len += hlen + _T_ALIGN_SIZEOF(*(ops->ttl)); if (ops->reuse) len += hlen + _T_ALIGN_SIZEOF(*(ops->reuse)); if (ops->norte) len += hlen + _T_ALIGN_SIZEOF(*(ops->norte)); if (ops->bcast) len += hlen + _T_ALIGN_SIZEOF(*(ops->bcast)); if (ss->p.prot.protocol == T_INET_TCP) { if (ops->nodly) len += hlen + _T_ALIGN_SIZEOF(*(ops->nodly)); if (ops->mss) len += hlen + _T_ALIGN_SIZEOF(*(ops->mss)); if (ops->alive) len += hlen + _T_ALIGN_SIZEOF(*(ops->alive)); } if (ss->p.prot.protocol == T_INET_UDP) { if (ops->csum) len += hlen + _T_ALIGN_SIZEOF(*(ops->csum)); }#if defined CONFIG_SCTP || defined CONFIG_SCTP_MODULE if (ss->p.prot.protocol == T_INET_SCTP) { if (ops->nodly) len += hlen + _T_ALIGN_SIZEOF(*(ops->nodly)); if (ops->cork) len += hlen + _T_ALIGN_SIZEOF(*(ops->cork)); if (ops->mss) len += hlen + _T_ALIGN_SIZEOF(*(ops->mss)); if (ops->ppi) len += hlen + _T_ALIGN_SIZEOF(*(ops->ppi)); if (ops->sid) len += hlen + _T_ALIGN_SIZEOF(*(ops->sid)); if (ops->ssn) len += hlen + _T_ALIGN_SIZEOF(*(ops->ssn)); if (ops->tsn) len += hlen + _T_ALIGN_SIZEOF(*(ops->tsn)); if (ops->recvopt) len += hlen + _T_ALIGN_SIZEOF(*(ops->recvopt)); if (ops->clife) len += hlen + _T_ALIGN_SIZEOF(*(ops->clife)); if (ops->sack) len += hlen + _T_ALIGN_SIZEOF(*(ops->sack)); if (ops->prtx) len += hlen + _T_ALIGN_SIZEOF(*(ops->prtx)); if (ops->artx) len += hlen + _T_ALIGN_SIZEOF(*(ops->artx)); if (ops->irtx) len += hlen + _T_ALIGN_SIZEOF(*(ops->irtx)); if (ops->hitvl) len += hlen + _T_ALIGN_SIZEOF(*(ops->hitvl)); if (ops->rtoinit) len += hlen + _T_ALIGN_SIZEOF(*(ops->rtoinit)); if (ops->rtomin) len += hlen + _T_ALIGN_SIZEOF(*(ops->rtomin)); if (ops->rtomax) len += hlen + _T_ALIGN_SIZEOF(*(ops->rtomax)); if (ops->ostr) len += hlen + _T_ALIGN_SIZEOF(*(ops->ostr)); if (ops->istr) len += hlen + _T_ALIGN_SIZEOF(*(ops->istr)); if (ops->cinc) len += hlen + _T_ALIGN_SIZEOF(*(ops->cinc)); if (ops->titvl) len += hlen + _T_ALIGN_SIZEOF(*(ops->titvl)); if (ops->mac) len += hlen + _T_ALIGN_SIZEOF(*(ops->mac)); if (ops->hb) len += hlen + _T_ALIGN_SIZEOF(*(ops->hb)); if (ops->rto) len += hlen + _T_ALIGN_SIZEOF(*(ops->rto)); if (ops->stat) len += hlen + _T_ALIGN_SIZEOF(*(ops->stat)); /* FIXME add more */ if (ops->debug) len += hlen + _T_ALIGN_SIZEOF(*(ops->debug)); }#endif } return (len);}STATIC voidss_build_opts(ss_t * ss, ss_opts_t * ops, unsigned char **p){ struct t_opthdr *oh; const size_t hlen = sizeof(struct t_opthdr); const size_t olen = hlen + sizeof(t_scalar_t); if (ops) { if (ops->opt) { oh = ((typeof(oh)) * p)++; oh->len = hlen + sizeof(struct ip_options); oh->level = T_INET_IP; oh->name = T_IP_OPTIONS; oh->status = (ops->flags & TF_IP_OPTIONS) ? T_SUCCESS : T_FAILURE; *((struct ip_options *) *p) = *(ops->opt); *p += _T_ALIGN_SIZEOF(*ops->opt); } if (ops->tos) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_IP; oh->name = T_IP_TOS; oh->status = (ops->flags & TF_IP_TOS) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->tos); *p += _T_ALIGN_SIZEOF(*ops->tos); } if (ops->ttl) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_IP; oh->name = T_IP_TTL; oh->status = (ops->flags & TF_IP_TTL) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->ttl); *p += _T_ALIGN_SIZEOF(*ops->ttl); } if (ops->reuse) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_IP; oh->name = T_IP_REUSEADDR; oh->status = (ops->flags & TF_IP_REUSEADDR) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->reuse); *p += _T_ALIGN_SIZEOF(*ops->reuse); } if (ops->norte) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_IP; oh->name = T_IP_DONTROUTE; oh->status = (ops->flags & TF_IP_DONTROUTE) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->norte); *p += _T_ALIGN_SIZEOF(*ops->norte); } if (ops->bcast) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_IP; oh->name = T_IP_BROADCAST; oh->status = (ops->flags & TF_IP_BROADCAST) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->bcast); *p += _T_ALIGN_SIZEOF(*ops->bcast); } if (ss->p.prot.protocol == T_INET_TCP) { if (ops->nodly) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_TCP; oh->name = T_TCP_NODELAY; oh->status = (ops->flags & TF_TCP_NODELAY) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->nodly); *p += _T_ALIGN_SIZEOF(*ops->nodly); } if (ops->mss) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_TCP; oh->name = T_TCP_MAXSEG; oh->status = (ops->flags & TF_TCP_MAXSEG) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->mss); *p += _T_ALIGN_SIZEOF(*ops->mss); } if (ops->alive) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_TCP; oh->name = T_TCP_KEEPALIVE; oh->status = (ops->flags & TF_TCP_KEEPALIVE) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->alive); *p += _T_ALIGN_SIZEOF(*ops->alive); } } if (ss->p.prot.protocol == T_INET_UDP) { if (ops->csum) { oh = ((typeof(oh)) * p)++; oh->len = olen; oh->level = T_INET_UDP; oh->name = T_UDP_CHECKSUM; oh->status = (ops->flags & TF_UDP_CHECKSUM) ? T_SUCCESS : T_FAILURE; *((t_scalar_t *) * p) = *(ops->csum); *p += _T_ALIGN_SIZEOF(*ops->csum); } } }}STATIC intss_parse_opts(ss_t * ss, ss_opts_t * ops, unsigned char *op, size_t len){ struct t_opthdr *oh; for (oh = _T_OPT_FIRSTHDR_OFS(op, len, 0); oh; oh = _T_OPT_NEXTHDR_OFS(op, len, oh, 0)) { switch (oh->level) { case T_INET_IP: switch (oh->name) { case T_IP_OPTIONS: ops->opt = (void *) _T_OPT_DATA_OFS(oh, 0); ops->flags |= TF_IP_OPTIONS; continue; case T_IP_TOS: ops->tos = (void *) _T_OPT_DATA_OFS(oh, 0); ops->flags |= TF_IP_TOS; continue; case T_IP_TTL: ops->ttl = (void *) _T_OPT_DATA_OFS(oh, 0); ops->flags |= TF_IP_TTL; continue; case T_IP_REUSEADDR: ops->reuse = (void *) _T_OPT_DATA_OFS(oh, 0); ops->flags |= TF_IP_REUSEADDR; continue; case T_IP_DONTROUTE: ops->norte = (void *) _T_OPT_DATA_OFS(oh, 0); ops->flags |= TF_IP_DONTROUTE; continue; case T_IP_BROADCAST:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -