/* Input vector for ACCESS ports */ static void ethsw_iv_access(ethsw_table_t *t,ethsw_packet_t *sp, netio_desc_t *op) { m_uint8_t pkt[ETHSW_MAX_PKT_SIZE+4]; switch(op->vlan_port_type) { /* Access -> Access: no special treatment */ case ETHSW_PORT_TYPE_ACCESS: netio_send(op,sp->pkt,sp->pkt_len); break; /* Access -> 802.1Q: push tag */ case ETHSW_PORT_TYPE_DOT1Q: /* * If the native VLAN of output port is the same as input, * forward the packet without adding the tag. */ if (op->vlan_id == sp->input_vlan) { netio_send(op,sp->pkt,sp->pkt_len); } else { dot1q_push_tag(pkt,sp,op->vlan_id,sp->input_port->ethertype); netio_send(op,pkt,sp->pkt_len+4); } break; default: fprintf(stderr,"ethsw_iv_access: unknown port type %u\n", op->vlan_port_type); } }
/* Input vector for QinQ ports */ static void ethsw_iv_qinq(ethsw_table_t *t,ethsw_packet_t *sp, netio_desc_t *op) { m_uint8_t pkt[ETHSW_MAX_PKT_SIZE+4]; switch(op->vlan_port_type) { /* QinQ -> 802.1Q: push outer tag */ case ETHSW_PORT_TYPE_DOT1Q: dot1q_push_tag(pkt,sp,sp->input_port->vlan_id,sp->input_port->ethertype); netio_send(op,pkt,sp->pkt_len+4); break; /* * QinQ -> QinQ: valid situation if we have the same customer connected * on two ports (so with identical VLAN id on tunnel ports). */ case ETHSW_PORT_TYPE_QINQ: if (sp->input_port->vlan_id == op->vlan_id) { dot1q_pop_tag(pkt,sp); netio_send(op,pkt,sp->pkt_len-4); } break; default: fprintf(stderr,"ethsw_iv_dot1q: unknown port type %u\n", op->vlan_port_type); } }
/* this is called when new data has arrived or the socket has been closed datalen < 1: socket closed! */ static void __netio_http_cb_data(int s, void *obj, char *data, int datalen) { netio_http_conn_t *conn = (netio_http_conn_t*)obj; int ret = -1; if (!netio_http_conn_lock(conn)) return; if (conn->forward_socket == -1) ret = __netio_http_parse_data(conn, data, datalen); else if (datalen > 0) { netio_send(conn->forward_socket, data, datalen); ret = 1; } if (ret > 0) { ship_unlock(conn); return; } if (!ret) { LOG_DEBUG("Got total %d bytes, %d data, code %d for request to %s\n", conn->data_len, conn->content_len, conn->resp_code, conn->fullurl); /* done doing a GET / POST */ if (conn->func) { netio_http_decode_encoding(conn); conn->func(conn->fullurl, conn->resp_code, &(conn->buf[conn->header_len]), conn->content_len, conn->pkg); conn->func = 0; } } netio_http_conn_close(conn); }
/* callback on tcp connections */ static void __netio_http_cb_conn(int s, void *obj) { netio_http_conn_t *h = (netio_http_conn_t*)obj; char *buf; if (!netio_http_conn_lock(h)) return; /* write the data! */ if ((buf = mallocz(strlen(post_header) + strlen(h->url) + zstrlen(h->content_type) + strlen(h->host) + 64 + h->data_len))) { int len = 0; if (h->buf) { sprintf(buf, post_header, h->url, h->host, h->data_len, h->content_type); len = strlen(buf); memcpy(buf + len, h->buf, h->data_len); } else { sprintf(buf, get_header, h->url, h->host); len = strlen(buf); } netio_send(s, buf, len + h->data_len); freez(buf); h->data_len = 0; ship_unlock(h); } else { netio_http_conn_close(h); } }
/* Input vector for 802.1Q ports */ static void ethsw_iv_dot1q(ethsw_table_t *t,ethsw_packet_t *sp, netio_desc_t *op) { m_uint8_t pkt[ETHSW_MAX_PKT_SIZE+4]; /* If we don't have an input tag, we work temporarily as an access port */ if (!sp->input_tag) { ethsw_iv_access(t,sp,op); return; } switch(op->vlan_port_type) { /* 802.1Q -> Access: pop tag */ case ETHSW_PORT_TYPE_ACCESS: dot1q_pop_tag(pkt,sp); netio_send(op,pkt,sp->pkt_len-4); break; /* 802.1Q -> 802.1Q: pop tag if native VLAN in output otherwise no-op */ case ETHSW_PORT_TYPE_DOT1Q: if (op->vlan_id == sp->input_vlan) { dot1q_pop_tag(pkt,sp); netio_send(op,pkt,sp->pkt_len-4); } else { netio_send(op,sp->pkt,sp->pkt_len); } break; /* * 802.1Q -> QinQ: pop outer tag if native VLAN in the one specified * tunnel port. */ case ETHSW_PORT_TYPE_QINQ: if (op->vlan_id == sp->input_vlan) { dot1q_pop_tag(pkt,sp); netio_send(op,pkt,sp->pkt_len-4); } break; default: fprintf(stderr,"ethsw_iv_dot1q: unknown port type %u\n", op->vlan_port_type); } }
void netio_http_respond_multipart(netio_http_conn_t *conn, char *content_type, char *data, int data_len) { const char *templ = "%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\n\r\n"; char *msg = mallocz(strlen(templ) + strlen(content_type) + 128); char *boundary = 0; /* if no header set yet, create one */ if (!(boundary = netio_http_get_attr(conn, "boundary"))) { netio_http_respond_multipart_header(conn, 200, "OK"); boundary = netio_http_get_attr(conn, "boundary"); } sprintf(msg, templ, boundary, content_type); netio_send(conn->socket, msg, strlen(msg)); netio_send(conn->socket, data, data_len); freez(msg); }
void netio_http_redirect(netio_http_conn_t *conn, char *url) { const char *templ = "HTTP/1.1 302 Found\r\nServer: P2PSHIP proxy\r\nLocation: %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"; char *msg = mallocz(strlen(templ) + strlen(url) + 128); if (!msg) return; sprintf(msg, templ, url); netio_send(conn->socket, msg, strlen(msg)); freez(msg); }
int flvsrv_cbWriteDataNet(void *pArg, const unsigned char *pData, unsigned int len) { int rc = 0; FLVSRV_CTXT_T *pFlvCtxt = (FLVSRV_CTXT_T *) pArg; if((rc = netio_send(&pFlvCtxt->pSd->netsocket, &pFlvCtxt->pSd->sain, pData, len)) < 0) { LOG(X_ERROR("Failed to send flv %s %u bytes, total: %llu)"), (pFlvCtxt->writeErrDescr ? pFlvCtxt->writeErrDescr : ""), len, pFlvCtxt->totXmit); } else { pFlvCtxt->totXmit += len; //write(pFlvCtxt->g_fd, pData, len); } return rc; }
void netio_http_respond(netio_http_conn_t *conn, int code, char *code_str, char *content_type, char *data, int data_len) { char *msg = 0; int len = 0; if (!netio_http_create_response(code, code_str, content_type, data, data_len, &msg, &len)) { netio_send(conn->socket, msg, len); freez(msg); } }
void netio_http_respond_auth(netio_http_conn_t *conn, char *realm, char *content_type, char *data) { const char *templ = "HTTP/1.1 407 Proxy Authorization Required\r\nServer: P2PSHIP proxy\r\nProxy-Authenticate: Basic realm=\"%s\"\r\nContent-Length: %d\r\nConnection: close\r\nContent-Type: %s\r\n\r\n"; char *msg = mallocz(strlen(templ) + strlen(realm) + strlen(data) + strlen(content_type) + 128); if (!msg) return; sprintf(msg, templ, realm, strlen(data), content_type); strcat(msg, data); netio_send(conn->socket, msg, strlen(msg)); freez(msg); }
/* Receive an ATM cell */ static int atm_bridge_recv_cell(netio_desc_t *nio, u_char *atm_cell,ssize_t cell_len, atm_bridge_t *t) { m_uint32_t atm_hdr,vpi,vci; int status,res = 0; if (cell_len != ATM_CELL_SIZE) return(-1); ATM_BRIDGE_LOCK(t); /* check the VPI/VCI */ atm_hdr = m_ntoh32(atm_cell); vpi = (atm_hdr & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; vci = (atm_hdr & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; if ((t->vpi != vpi) || (t->vci != vci)) goto done; if ((status = atm_aal5_recv(&t->arc,atm_cell)) == 1) { /* Got AAL5 packet, check RFC1483b encapsulation */ if ((t->arc.len > ATM_RFC1483B_HLEN) && !memcmp(t->arc.buffer,atm_rfc1483b_header,ATM_RFC1483B_HLEN)) { netio_send(t->eth_nio, t->arc.buffer+ATM_RFC1483B_HLEN, t->arc.len-ATM_RFC1483B_HLEN); } atm_aal5_recv_reset(&t->arc); } else { if (status < 0) { atm_aal5_recv_reset(&t->arc); res = -1; } } done: ATM_BRIDGE_UNLOCK(t); return(res); }
/* Send contents of a SDMA buffer */ static void mv64460_sdma_send_buffer(struct mv64460_data *d,u_int chan_id, u_char *buffer,m_uint32_t len) { struct mpsc_channel *channel; u_int mode; channel = &d->mpsc[chan_id]; mode = mv64460_mpsc_get_channel_mode(d,chan_id); switch(mode) { case MV64460_MPSC_MODE_HDLC: if (channel->nio != NULL) netio_send(channel->nio,buffer,len); break; case MV64460_MPSC_MODE_UART: if (channel->vtty != NULL) vtty_put_buffer(channel->vtty,(char *)buffer,len); break; } }
void netio_http_respond_multipart_header(netio_http_conn_t *conn, int code, char *code_str) { const char *templ = "HTTP/1.1 %d %s\r\nServer: P2PSHIP proxy\r\nConnection: close\r\nContent-Type: multipart/mixed;\r\n boundary=\"%s\"\r\n\r\n"; char *msg = mallocz(strlen(templ) + strlen(code_str) + 128); int i = 0; char boundary[32]; if (!msg) return; for (i = 0; i < sizeof(boundary)-1; i++) { if (i < 5) boundary[i] = '-'; else boundary[i] = 'a' + (rand() % 20); } boundary[sizeof(boundary)-1] = 0; netio_http_set_attr(conn, "boundary", boundary); sprintf(msg, templ, code, code_str, boundary); netio_send(conn->socket, msg, strlen(msg)); freez(msg); }
/* callback when data is got */ static void __netio_http_conn_read_cb(int s, char *data, ssize_t datalen) { netio_http_conn_t *conn = 0; int ret = -1; char *newbuf = NULL; ASSERT_TRUE(conn = netio_http_get_conn_by_socket(s, 1), err); if (datalen < 1) { goto err; } // todo: some sort of half- ready handling #connect // forward-tunnel also!! if (conn->forward_socket != -1) { if (datalen > 0) { netio_send(conn->forward_socket, data, datalen); ret = 1; } } else if (conn->service_forward_service) { int l2; /* add tracking id to buffer */ l2 = datalen + strlen(conn->tracking_id) + 1; ASSERT_TRUE(newbuf = mallocz(l2+1), err); strcpy(newbuf, conn->tracking_id); strcat(newbuf, "\n"); memcpy(newbuf+strlen(newbuf), data, datalen); ASSERT_ZERO(conn_send_slow(conn->service_forward_to, conn->service_forward_from, conn->service_forward_service, newbuf, l2, NULL, NULL), err); ret = 1; } else if (datalen > 0) { ret = __netio_http_parse_data(conn, data, datalen); } /* process.. */ while (!ret) { netio_http_conn_t *new_conn = 0; ret = __netio_http_process_req(conn); // should ret be checked?? if (!strcmp(conn->method, "CONNECT")) break; if (!strcmp(conn->http_version, "HTTP/1.0")) { ret = -1; goto err; } /* we create a new conn for this socket as there might be another request coming. This instead of clearing the one as .. the http proxy will close the http_conn if after responding to just one request. */ netio_http_cut_overrun(conn, &data, &datalen); ship_unlock(conn); ASSERT_TRUE(new_conn = netio_http_conn_new(s), err); memcpy(&(new_conn->addr), &(conn->addr), sizeof(addr_t)); new_conn->ss = conn->ss; conn->owns_socket = 0; /* ..parse the data at this point, it IS pointing at the buffer in the old conn! */ if (datalen > 0) ret = __netio_http_parse_data(new_conn, data, datalen); else ret = 1; ship_unlock(new_conn); netio_http_conn_lock(conn); if (ret < 1) { netio_http_conn_close(conn); } else { ship_unlock(conn); } netio_http_conn_lock(new_conn); conn = new_conn; } err: if (ret < 1) { netio_http_conn_close(conn); } else if (conn) { ship_unlock(conn); } }
/* Handle the TX ring */ static int dev_pos_oc3_handle_txring(struct pos_oc3_data *d) { u_char pkt[POS_OC3_MAX_PKT_SIZE],*pkt_ptr; m_uint32_t clen,tot_len,norm_len; m_uint32_t tx_start,addr; struct tx_desc txd0,ctxd,*ptxd; int i,done = FALSE; if ((d->tx_start == 0) || (d->nio == NULL)) return(FALSE); /* Copy the current txring descriptor */ tx_start = d->tx_current; ptxd = &txd0; txdesc_read(d,d->tx_current,ptxd); /* If we don't own the descriptor, we cannot transmit */ if (!(txd0.tdes[0] & POS_OC3_TXDESC_OWN)) return(FALSE); #if DEBUG_TRANSMIT POS_LOG(d,"pos_oc3_handle_txring: 1st desc: tdes[0]=0x%x, tdes[1]=0x%x\n", ptxd->tdes[0],ptxd->tdes[1]); #endif pkt_ptr = pkt; tot_len = 0; i = 0; do { #if DEBUG_TRANSMIT POS_LOG(d,"pos_oc3_handle_txring: loop: tdes[0]=0x%x, tdes[1]=0x%x\n", ptxd->tdes[0],ptxd->tdes[1]); #endif if (!(ptxd->tdes[0] & POS_OC3_TXDESC_OWN)) { POS_LOG(d,"pos_oc3_handle_txring: descriptor not owned!\n"); return(FALSE); } clen = ptxd->tdes[0] & POS_OC3_TXDESC_LEN_MASK; /* Be sure that we have length not null */ if (clen != 0) { addr = ptxd->tdes[1]; norm_len = normalize_size(clen,4,0); physmem_copy_from_vm(d->vm,pkt_ptr,addr,norm_len); mem_bswap32(pkt_ptr,norm_len); } pkt_ptr += clen; tot_len += clen; /* Clear the OWN bit if this is not the first descriptor */ if (i != 0) physmem_copy_u32_to_vm(d->vm,d->tx_current,0); /* Go to the next descriptor */ txdesc_set_next(d,ptxd); /* Copy the next txring descriptor */ if (ptxd->tdes[0] & POS_OC3_TXDESC_CONT) { txdesc_read(d,d->tx_current,&ctxd); ptxd = &ctxd; i++; } else done = TRUE; }while(!done); if (tot_len != 0) { #if DEBUG_TRANSMIT POS_LOG(d,"sending packet of %u bytes (flags=0x%4.4x)\n", tot_len,txd0.tdes[0]); mem_dump(log_file,pkt,tot_len); #endif /* send it on wire */ netio_send(d->nio,pkt,tot_len); } /* Clear the OWN flag of the first descriptor */ txd0.tdes[0] &= ~POS_OC3_TXDESC_OWN; physmem_copy_u32_to_vm(d->vm,tx_start,txd0.tdes[0]); /* Interrupt on completion */ pci_dev_trigger_irq(d->vm,d->pci_dev); return(TRUE); }