static void np_close_channels(void){ int i; for(i = 0; i < NPCAST_NUM_CHANNELS; ++i) close_channel(i); }
OPJ_BOOL process_JPIPrequest( server_record_t *rec, QR_t *qr) { target_param_t *target = NULL; session_param_t *cursession = NULL; channel_param_t *curchannel = NULL; if( qr->query->target || qr->query->tid){ if( !identify_target( *(qr->query), rec->targetlist, &target)) return OPJ_FALSE; } if( qr->query->cid){ if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) return OPJ_FALSE; qr->channel = curchannel; } if( qr->query->cnew != non){ if( !open_channel( *(qr->query), rec->sessionlist, rec->auxtrans, target, &cursession, &curchannel)) return OPJ_FALSE; qr->channel = curchannel; } if( qr->query->cclose) if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) return OPJ_FALSE; if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0 || qr->query->len > 0) if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue)) return OPJ_FALSE; return OPJ_TRUE; }
/************************************************************************** * WsCloseChannel [webservices.@] */ HRESULT WINAPI WsCloseChannel( WS_CHANNEL *handle, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; TRACE( "%p %p %p\n", handle, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); return close_channel( channel ); }
/************************************************************************** * WsCloseServiceProxy [webservices.@] */ HRESULT WINAPI WsCloseServiceProxy( WS_SERVICE_PROXY *handle, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct proxy *proxy = (struct proxy *)handle; TRACE( "%p %p %p\n", handle, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); return close_channel( proxy->channel ); }
static int etherloop_deassign (OZ_Devunit *devunit, void *devexv, OZ_Iochan *iochan, void *chnexv) { Chnex *chnex; Devex *devex; uLong dv; chnex = chnexv; devex = devexv; if (chnex -> rxreqt != NULL) { dv = oz_hw_smplock_wait (&(devex -> smplock)); close_channel (devex, chnex, dv); oz_hw_smplock_clr (&(devex -> smplock), dv); if (chnex -> rxreqt != NULL) oz_crash ("oz_dev_etherloop deassign: channel still open after close"); } return (0); }
static amqp_boolean_t check_channel_status(connstate_t *conn, amqp_frame_t *frame, chanstate_t *chan) { if (chan->status) { if (amqp_constant_is_hard_error(chan->status)) { close_connection(conn, chan->status, "Connection error %s (%d) in response to %s", amqp_constant_name(chan->status), chan->status, amqp_method_name(frame->payload.method.id)); } else { close_channel(conn, chan->channel, chan->status, "Channel error %s (%d) in response to %s", amqp_constant_name(chan->status), chan->status, amqp_method_name(frame->payload.method.id)); } return 1; } else { return 0; } }
int main(int argc, char *argv[]) { struct socket *sock; struct sockaddr_in addr; socklen_t addr_len; char line[LINE_LENGTH + 1]; unsigned int unordered, policy, value, id, seconds; unsigned int i; struct channel *channel; const int on = 1; struct sctp_assoc_value av; struct sctp_event event; struct sctp_udpencaps encaps; struct sctp_initmsg initmsg; uint16_t event_types[] = {SCTP_ASSOC_CHANGE, SCTP_PEER_ADDR_CHANGE, SCTP_REMOTE_ERROR, SCTP_SHUTDOWN_EVENT, SCTP_ADAPTATION_INDICATION, SCTP_SEND_FAILED_EVENT, SCTP_STREAM_RESET_EVENT, SCTP_STREAM_CHANGE_EVENT}; if (argc > 1) { usrsctp_init(atoi(argv[1]), NULL, debug_printf); } else { usrsctp_init(9899, NULL, debug_printf); } #ifdef SCTP_DEBUG usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); #endif usrsctp_sysctl_set_sctp_blackhole(2); if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &peer_connection)) == NULL) { perror("socket"); } init_peer_connection(&peer_connection); if (argc > 2) { memset(&encaps, 0, sizeof(struct sctp_udpencaps)); encaps.sue_address.ss_family = AF_INET6; encaps.sue_port = htons(atoi(argv[2])); if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { perror("setsockopt"); } } if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) { perror("setsockopt SCTP_RECVRCVINFO"); } if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &on, sizeof(int)) < 0) { perror("setsockopt SCTP_EXPLICIT_EOR"); } /* Allow resetting streams. */ av.assoc_id = SCTP_ALL_ASSOC; av.assoc_value = SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ; if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof(struct sctp_assoc_value)) < 0) { perror("setsockopt SCTP_ENABLE_STREAM_RESET"); } /* Enable the events of interest. */ memset(&event, 0, sizeof(event)); event.se_assoc_id = SCTP_ALL_ASSOC; event.se_on = 1; for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) { event.se_type = event_types[i]; if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) { perror("setsockopt SCTP_EVENT"); } } memset(&initmsg, 0, sizeof(struct sctp_initmsg)); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 65535; if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg)) < 0) { perror("setsockopt SCTP_INITMSG"); } if (argc == 5) { /* operating as client */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; #ifdef HAVE_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_addr.s_addr = inet_addr(argv[3]); addr.sin_port = htons(atoi(argv[4])); if (usrsctp_connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("connect"); } printf("Connected to %s:%d.\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); } else if (argc == 4) { struct socket *conn_sock; /* operating as server */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; #ifdef HAVE_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(atoi(argv[3])); if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("bind"); } if (usrsctp_listen(sock, 1) < 0) { perror("listen"); } addr_len = (socklen_t)sizeof(struct sockaddr_in); memset(&addr, 0, sizeof(struct sockaddr_in)); if ((conn_sock = usrsctp_accept(sock, (struct sockaddr *)&addr, &addr_len)) == NULL) { perror("accept"); } usrsctp_close(sock); sock = conn_sock; printf("Connected to %s:%d.\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); } else { printf("Usage: %s local_udp_port remote_udp_port local_port when operating as server\n" " %s local_udp_port remote_udp_port remote_addr remote_port when operating as client\n", argv[0], argv[0]); return (0); } lock_peer_connection(&peer_connection); peer_connection.sock = sock; unlock_peer_connection(&peer_connection); for (;;) { #ifdef _WIN32 if (gets_s(line, LINE_LENGTH) == NULL) { #else if (fgets(line, LINE_LENGTH, stdin) == NULL) { #endif if (usrsctp_shutdown(sock, SHUT_WR) < 0) { perror("usrsctp_shutdown"); } while (usrsctp_finish() != 0) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif } break; } if (strncmp(line, "?", strlen("?")) == 0 || strncmp(line, "help", strlen("help")) == 0) { printf("Commands:\n" "open unordered pr_policy pr_value - opens a channel\n" "close channel - closes the channel\n" "send channel:string - sends string using channel\n" "status - prints the status\n" "sleep n - sleep for n seconds\n" "help - this message\n"); } else if (strncmp(line, "status", strlen("status")) == 0) { lock_peer_connection(&peer_connection); print_status(&peer_connection); unlock_peer_connection(&peer_connection); } else if (strncmp(line, "quit", strlen("quit")) == 0) { if (usrsctp_shutdown(sock, SHUT_WR) < 0) { perror("usrsctp_shutdown"); } while (usrsctp_finish() != 0) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif } break; } else if (sscanf(line, "open %u %u %u", &unordered, &policy, &value) == 3) { lock_peer_connection(&peer_connection); channel = open_channel(&peer_connection, (uint8_t)unordered, (uint16_t)policy, (uint32_t)value); unlock_peer_connection(&peer_connection); if (channel == NULL) { printf("Creating channel failed.\n"); } else { printf("Channel with id %u created.\n", channel->id); } } else if (sscanf(line, "close %u", &id) == 1) { if (id < NUMBER_OF_CHANNELS) { lock_peer_connection(&peer_connection); close_channel(&peer_connection, &peer_connection.channels[id]); unlock_peer_connection(&peer_connection); } } else if (sscanf(line, "send %u", &id) == 1) { if (id < NUMBER_OF_CHANNELS) { char *msg; msg = strstr(line, ":"); if (msg) { msg++; lock_peer_connection(&peer_connection); #ifdef _WIN32 if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg))) { #else if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg) - 1)) { #endif printf("Message sent.\n"); } else { printf("Message sending failed.\n"); } unlock_peer_connection(&peer_connection); } } } else if (sscanf(line, "sleep %u", &seconds) == 1) { #ifdef _WIN32 Sleep(seconds * 1000); #else sleep(seconds); #endif } else { printf("Unknown command: %s", line); } } return (0); }
void *client(void *arg) { channel_t channel = (channel_t)arg; uint32_t major_stat; uint32_t minor_stat; uint32_t rflags; uint32_t inout_gssd_flags; gssd_cred cred_handle = (gssd_cred) (uintptr_t)GSS_C_NO_CREDENTIAL; gssd_ctx gss_context = (gssd_ctx) (uintptr_t)GSS_C_NO_CONTEXT; kern_return_t kr; int gss_error = 0; int retry_count = 0; char display_name[128]; do { if (read_channel(1, channel)) { Log("Bad read from server\n"); return (NULL); } if (verbose) Debug("Calling mach_gss_init_sec_context from %p\n", (void *) pthread_self()); deallocate(channel->ctoken, channel->ctokenCnt); channel->ctoken = (gssd_byte_buffer)GSS_C_NO_BUFFER; channel->ctokenCnt = 0; retry: switch (version) { case 0: case 1: kr = mach_gss_init_sec_context( client_mp, mech, channel->stoken, channel->stokenCnt, uid, principal, svcname, flags, gssd_flags, &gss_context, &cred_handle, &rflags, &channel->clnt_skey, &channel->clnt_skeyCnt, &channel->ctoken, &channel->ctokenCnt, &major_stat, &minor_stat); break; case 2: inout_gssd_flags = gssd_flags; kr = mach_gss_init_sec_context_v2( client_mp, mech, channel->stoken, channel->stokenCnt, uid, clientp.nt, clientp.name, clientp.len, targetp.nt, targetp.name, targetp.len, flags, &inout_gssd_flags, &gss_context, &cred_handle, &rflags, &channel->clnt_skey, &channel->clnt_skeyCnt, &channel->ctoken, &channel->ctokenCnt, display_name, &major_stat, &minor_stat); if (verbose && kr == KERN_SUCCESS && major_stat == GSS_S_COMPLETE) Debug("Got client identity of '%s'\n", display_name); break; default: Log("Unsupported version %d\n", version); exit(1); break; } if (kr != KERN_SUCCESS) { OSAtomicIncrement32(&server_errors); Log("gsstest client: %s\n", mach_error_string(kr)); if (exitonerror) exit(1); if (kr == MIG_SERVER_DIED) { OSAtomicIncrement32(&server_deaths); if (gss_context == (uint32_t)(uintptr_t)GSS_C_NO_CONTEXT && retry_count < max_retries) { retry_count++; goto retry; } } channel->failure = 1; write_channel(1, channel); return (NULL); } gss_error = (major_stat != GSS_S_COMPLETE && major_stat != GSS_S_CONTINUE_NEEDED); if (verbose > 1) { Debug("\tcred = 0x%0x\n", (int) cred_handle); Debug("\tclnt_gss_context = 0x%0x\n", (int) gss_context); Debug("\ttokenCnt = %d\n", (int) channel->ctokenCnt); if (verbose > 2) HexDump((char *) channel->ctoken, (uint32_t) channel->ctokenCnt); } channel->failure = gss_error; write_channel(1, channel); } while (major_stat == GSS_S_CONTINUE_NEEDED); if (gss_error) { OSAtomicIncrement32(&gss_init_errors); Log("mach_gss_int_sec_context: %#K %#k\n", major_stat, mechtab[mech], minor_stat); } close_channel(1, channel); return (NULL); }
int main(int argc, char ** argv) { int sc_fifo_fd, cs_fifo_fd; /* Mandatory arguments */ if( !argv[1] || !argv[2] || !argv[3] || !argv[4] ) { fprintf(stderr,"client [server->client fifo] [client->server fifo] [password file] [username]\n"); exit(1); } /* Create connection with the server */ fprintf(stderr,"Create connection...\n"); sc_fifo_fd = open_channel(argv[1]); cs_fifo_fd = open_channel(argv[2]); write_msg(cs_fifo_fd,(const u_int8_t *)CONNECTION_STRING,strlen(CONNECTION_STRING)); /* Read OK */ if( read_string(sc_fifo_fd,OK_STRING) < 0 ) { fprintf(stderr,"Communication error\n"); goto next1; } /* Server authentication */ write_msg(cs_fifo_fd,(const u_int8_t *)"A",1); // GET public rsa key of S, (s_puk,n), from "client_folder/server_rsa_public_key.txt" /* ... */ // CREATE a random number r /* ... */ // ENCRYPT r using (s_puk,n) -> c = r^s_puk mod n /* ... */ // WRITE c to S /* ... */ // READ r' from C /* ... */ // CHECK if r = r' /* ... */ /* Client authentication */ // SEND client_name to S /* ... */ // GET private rsa key of C, (s_prk,n) from "client_folder/client_rsa_private_key.txt" /* ... */ // READ c from S /* ... */ // DECRYPT c using (c_prk,n) -> r' = c^c_prk mod n /* ... */ // WRITE r' to S /* ... */ // GET private rsa key of C, c_prk from "client_folder/client_rsa_private_key.txt" /* ... */ /* Negotiation of the cipher suite */ /* ... */ /* Negotiation of the private key */ /* ... */ /* Encrypt communication */ /* ... */ /* Disconnection */ /* ... */ next1: // to be used when server writes the BYE string /* Close connection with the server */ fprintf(stderr,"Closing connection...\n"); /* Expect BYE */ if( read_string(sc_fifo_fd,CLOSE_CONNECTION_STRING) < 0 ) { fprintf(stderr,"Communication error\n"); goto next1; } close_channel(cs_fifo_fd); close_channel(sc_fifo_fd); exit(0) ; next2: // to be used when client writes the BYE string /* Close current connection */ fprintf(stderr,"Closing connection...\n"); write_BYE(cs_fifo_fd); close_channel(cs_fifo_fd); close_channel(sc_fifo_fd); exit(0); }
static uLong etherloop_start (OZ_Devunit *devunit, void *devexv, OZ_Iochan *iochan, void *chnexv, OZ_Procmode procmode, OZ_Ioop *ioop, void *iopexv, uLong funcode, uLong as, void *ap) { Chnex *chnex; Devex *devex; Iopex *iopex, **liopex; int i; uLong dv, sts; Rxbuf *rxbuf; chnex = chnexv; devex = devexv; iopex = iopexv; switch (funcode) { /* Open - associates a protocol number with a channel and starts reception */ case OZ_IO_ETHER_OPEN: { OZ_IO_ether_open ether_open; movc4 (as, ap, sizeof ether_open, ðer_open); /* Make sure not already open */ dv = oz_hw_smplock_wait (&(devex -> smplock)); if (chnex -> rxreqt != NULL) { oz_hw_smplock_clr (&(devex -> smplock), dv); return (OZ_FILEALREADYOPEN); } /* Put channel on list of open channels */ chnex -> proto = N2HW (ether_open.proto); chnex -> promis = ether_open.promis; chnex -> rxreqt = &(chnex -> rxreqh); chnex -> next = devex -> chnexs; devex -> chnexs = chnex; oz_hw_smplock_clr (&(devex -> smplock), dv); return (OZ_SUCCESS); } /* Disassociates a protocol with a channel and stops reception */ case OZ_IO_ETHER_CLOSE: { dv = oz_hw_smplock_wait (&(devex -> smplock)); i = close_channel (devex, chnex, dv); oz_hw_smplock_clr (&(devex -> smplock), dv); return (i ? OZ_SUCCESS : OZ_FILENOTOPEN); } /* Receive a message */ case OZ_IO_ETHER_RECEIVE: { /* Get parameter block into iopex for future reference */ movc4 (as, ap, sizeof iopex -> receive, &(iopex -> receive)); /* If any of the rcv... parameters are filled in, it must be called from kernel mode */ if ((iopex -> receive.rcvfre != NULL) || (iopex -> receive.rcvdrv_r != NULL) || (iopex -> receive.rcveth_r != NULL)) { if (procmode != OZ_PROCMODE_KNL) return (OZ_KERNELONLY); } /* Set up the request parameters and queue request so the interrupt routine can fill the buffer with an incoming message */ iopex -> ioop = ioop; iopex -> next = NULL; iopex -> procmode = procmode; iopex -> devex = devex; rxbuf = iopex -> receive.rcvfre; /* maybe requestor has a buffer to free off */ if ((rxbuf != NULL) && (oz_hw_atomic_inc_long (&(rxbuf -> refcount), -1) == 0)) OZ_KNL_NPPFREE (rxbuf); dv = oz_hw_smplock_wait (&(devex -> smplock)); /* lock database */ liopex = chnex -> rxreqt; sts = OZ_FILENOTOPEN; /* make sure channel is still open */ if (liopex != NULL) { *liopex = iopex; /* put reqeuest on end of queue - transmit routine can now see it */ chnex -> rxreqt = &(iopex -> next); sts = OZ_STARTED; } oz_hw_smplock_clr (&(devex -> smplock), dv); return (sts); } /* Free a receive buffer */ case OZ_IO_ETHER_RECEIVEFREE: { OZ_IO_ether_receivefree ether_receivefree; if (procmode != OZ_PROCMODE_KNL) return (OZ_KERNELONLY); /* can only be called from kernel mode */ movc4 (as, ap, sizeof ether_receivefree, ðer_receivefree); /* get the parameters */ rxbuf = ether_receivefree.rcvfre; /* point to the buffer */ if (oz_hw_atomic_inc_long (&(rxbuf -> refcount), -1) == 0) OZ_KNL_NPPFREE (rxbuf); /* free it if no one else using it */ return (OZ_SUCCESS); } /* Allocate a send buffer */ case OZ_IO_ETHER_TRANSMITALLOC: { OZ_IO_ether_transmitalloc ether_transmitalloc; if (procmode != OZ_PROCMODE_KNL) return (OZ_KERNELONLY); /* can only be called from kernel mode */ movc4 (as, ap, sizeof ether_transmitalloc, ðer_transmitalloc); /* get the parameters */ rxbuf = OZ_KNL_NPPMALLOQ (sizeof *rxbuf); /* allocate a receive buffer */ if (rxbuf == NULL) return (OZ_EXQUOTANPP); if (ether_transmitalloc.xmtsiz_r != NULL) *(ether_transmitalloc.xmtsiz_r) = OZ_IO_ETHER_MAXDATA; /* this is size of data it can handle */ if (ether_transmitalloc.xmtdrv_r != NULL) *(ether_transmitalloc.xmtdrv_r) = rxbuf; /* this is the pointer we want returned in ether_transmit.xmtdrv */ if (ether_transmitalloc.xmteth_r != NULL) *(ether_transmitalloc.xmteth_r) = (uByte *)&(rxbuf -> buf); /* this is where they put the ethernet packet to be transmitted */ return (OZ_SUCCESS); } /* Transmit a message */ case OZ_IO_ETHER_TRANSMIT: { OZ_IO_ether_transmit ether_transmit; /* Get parameter block into iopex for future reference */ movc4 (as, ap, sizeof ether_transmit, ðer_transmit); /* Any xmt... parameters require caller to be in kernel mode */ if ((ether_transmit.xmtdrv != NULL) || (ether_transmit.xmtdrv_r != NULL) || (ether_transmit.xmtsiz_r != NULL) || (ether_transmit.xmteth_r != NULL)) { if (procmode != OZ_PROCMODE_KNL) return (OZ_KERNELONLY); if (ether_transmit.xmtsiz_r != NULL) *(ether_transmit.xmtsiz_r) = 0; if (ether_transmit.xmtdrv_r != NULL) *(ether_transmit.xmtdrv_r) = NULL; if (ether_transmit.xmteth_r != NULL) *(ether_transmit.xmteth_r) = NULL; } /* See if they gave us a system buffer */ if (ether_transmit.xmtdrv != NULL) rxbuf = ether_transmit.xmtdrv; /* If not, allocate one */ else if (ether_transmit.buff == NULL) return (OZ_MISSINGPARAM); else { rxbuf = OZ_KNL_NPPMALLOQ (sizeof *rxbuf); if (rxbuf == NULL) return (OZ_EXQUOTANPP); } /* Anyway, copy in any data that they supplied */ if (ether_transmit.buff != NULL) { oz_knl_printk ("oz_dev_ip*: #1 %u < %u\n", ether_transmit.size, rxbuf -> buf.data - (uByte *)&(rxbuf -> buf)); oz_knl_printk ("oz_dev_ip*: #2 %u > %u\n", ether_transmit.size, sizeof rxbuf -> buf); if (ether_transmit.size < rxbuf -> buf.data - (uByte *)&(rxbuf -> buf)) sts = OZ_BADBUFFERSIZE; /* have to give at least the ethernet header stuff */ else if (ether_transmit.size > sizeof rxbuf -> buf) sts = OZ_BADBUFFERSIZE; /* can't give us more than buffer can hold */ else sts = oz_knl_section_uget (procmode, ether_transmit.size, ether_transmit.buff, &(rxbuf -> buf)); /* copy it in */ oz_knl_printk ("oz_dev_ip*: #3 %u < %u\n", ether_transmit.size, rxbuf -> dlen + rxbuf -> buf.data - (uByte *)&(rxbuf -> buf)); if ((sts == OZ_SUCCESS) && (ether_transmit.size < rxbuf -> dlen + rxbuf -> buf.data - (uByte *)&(rxbuf -> buf))) sts = OZ_BADBUFFERSIZE; /* must give enough to cover the dlen */ if (sts != OZ_SUCCESS) { OZ_KNL_NPPFREE (rxbuf); return (sts); } } /* Make sure dlen (length of data not including header) not too int */ oz_knl_printk ("oz_dev_ip*: #4 %u > %u\n", rxbuf -> dlen, DATASIZE); if (rxbuf -> dlen > DATASIZE) { /* can't be longer than hardware will allow */ OZ_KNL_NPPFREE (rxbuf); /* free off internal buffer */ return (OZ_BADBUFFERSIZE); /* return error status */ } /* Process it - hopefully there is a receive request to process it - if not, data is lost */ buffereceived (devex, rxbuf); /* If caller requested, allocate a transmit buffer to replace one used */ if (ether_transmit.xmtdrv_r != NULL) { rxbuf = OZ_KNL_NPPMALLOQ (sizeof *rxbuf); if (rxbuf == NULL) return (OZ_EXQUOTANPP); if (ether_transmit.xmtsiz_r != NULL) *(ether_transmit.xmtsiz_r) = OZ_IO_ETHER_MAXDATA; if (ether_transmit.xmtdrv_r != NULL) *(ether_transmit.xmtdrv_r) = rxbuf; if (ether_transmit.xmteth_r != NULL) *(ether_transmit.xmteth_r) = (uByte *)&(rxbuf -> buf); } return (OZ_SUCCESS); } /* Get info - part 1 */ case OZ_IO_ETHER_GETINFO1: { OZ_IO_ether_getinfo1 ether_getinfo1; movc4 (as, ap, sizeof ether_getinfo1, ðer_getinfo1); if (ether_getinfo1.enaddrbuff != NULL) { if (ether_getinfo1.enaddrsize > ADDRSIZE) ether_getinfo1.enaddrsize = ADDRSIZE; sts = oz_knl_section_uput (procmode, ether_getinfo1.enaddrsize, devex -> enaddr, ether_getinfo1.enaddrbuff); if (sts != OZ_SUCCESS) return (sts); } ether_getinfo1.datasize = DATASIZE; // max length of data portion of message ether_getinfo1.buffsize = BUFFSIZE; // max length of whole message (header, data, crc) ether_getinfo1.dstaddrof = 0; // offset of dest address in packet ether_getinfo1.srcaddrof = 0 + ADDRSIZE; // offset of source address in packet ether_getinfo1.protooffs = 0 + 2 * ADDRSIZE; // offset of protocol in packet ether_getinfo1.dataoffset = 0 + 2 * ADDRSIZE + PROTOSIZE; // offset of data in packet ether_getinfo1.arphwtype = ARPHWTYPE; // ARP hardware type ether_getinfo1.addrsize = ADDRSIZE; // size of each address field ether_getinfo1.protosize = PROTOSIZE; // size of protocol field if (as > sizeof ether_getinfo1) as = sizeof ether_getinfo1; sts = oz_knl_section_uput (procmode, as, ðer_getinfo1, ap); return (sts); } } return (OZ_BADIOFUNC); }
int main(int argc, char *argv[]) { int daemonize = 0; char *pidfile = NULL; char *envarea = NULL; int cnid = -1; pcre *msgfilter = NULL; pcre *stdfilter = NULL; int argi; struct sigaction sa; RbtIterator handle; /* Dont save the error buffer */ save_errbuf = 0; /* Create the peer container */ peers = rbtNew(name_compare); for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--debug")) { debug = 1; } else if (argnmatch(argv[argi], "--channel=")) { char *cn = strchr(argv[argi], '=') + 1; for (cnid = C_STATUS; (channelnames[cnid] && strcmp(channelnames[cnid], cn)); cnid++) ; if (channelnames[cnid] == NULL) cnid = -1; } else if (argnmatch(argv[argi], "--daemon")) { daemonize = 1; } else if (argnmatch(argv[argi], "--no-daemon")) { daemonize = 0; } else if (argnmatch(argv[argi], "--pidfile=")) { char *p = strchr(argv[argi], '='); pidfile = strdup(p+1); } else if (argnmatch(argv[argi], "--log=")) { char *p = strchr(argv[argi], '='); logfn = strdup(p+1); } else if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (argnmatch(argv[argi], "--locator=")) { char *p = strchr(argv[argi], '='); locator_init(p+1); locatorbased = 1; } else if (argnmatch(argv[argi], "--service=")) { char *p = strchr(argv[argi], '='); locatorservice = get_servicetype(p+1); } else if (argnmatch(argv[argi], "--filter=")) { char *p = strchr(argv[argi], '='); msgfilter = compileregex(p+1); if (!msgfilter) { errprintf("Invalid filter (bad expression): %s\n", p+1); } else { stdfilter = compileregex("^@@(logrotate|shutdown|drophost|droptest|renamehost|renametest)"); } } else { char *childcmd; char **childargs; int i = 0; childcmd = argv[argi]; childargs = (char **) calloc((1 + argc - argi), sizeof(char *)); while (argi < argc) { childargs[i++] = argv[argi++]; } addlocalpeer(childcmd, childargs); } } /* Sanity checks */ if (cnid == -1) { errprintf("No channel/unknown channel specified\n"); return 1; } if (locatorbased && (locatorservice == ST_MAX)) { errprintf("Must specify --service when using locator\n"); return 1; } if (!locatorbased && (rbtBegin(peers) == rbtEnd(peers))) { errprintf("Must specify command for local worker\n"); return 1; } /* Do cache responses to avoid doing too many lookups */ if (locatorbased) locator_prepcache(locatorservice, 0); /* Go daemon */ if (daemonize) { /* Become a daemon */ pid_t daemonpid = fork(); if (daemonpid < 0) { /* Fork failed */ errprintf("Could not fork child\n"); exit(1); } else if (daemonpid > 0) { /* Parent creates PID file and exits */ FILE *fd = NULL; if (pidfile) fd = fopen(pidfile, "w"); if (fd) { fprintf(fd, "%d\n", (int)daemonpid); fclose(fd); } exit(0); } /* Child (daemon) continues here */ setsid(); } /* Catch signals */ setup_signalhandler("xymond_channel"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); signal(SIGALRM, SIG_IGN); /* Switch stdout/stderr to the logfile, if one was specified */ freopen("/dev/null", "r", stdin); /* xymond_channel's stdin is not used */ if (logfn) { freopen(logfn, "a", stdout); freopen(logfn, "a", stderr); } /* Attach to the channel */ channel = setup_channel(cnid, CHAN_CLIENT); if (channel == NULL) { errprintf("Channel not available\n"); running = 0; } while (running) { /* * Wait for GOCLIENT to go up. * * Note that we use IPC_NOWAIT if there are messages in the * queue, because then we just want to pick up a message if * there is one, and if not we want to continue pushing the * queued data to the worker. */ struct sembuf s; int n; s.sem_num = GOCLIENT; s.sem_op = -1; s.sem_flg = ((pendingcount > 0) ? IPC_NOWAIT : 0); n = semop(channel->semid, &s, 1); if (n == 0) { /* * GOCLIENT went high, and so we got alerted about a new * message arriving. Copy the message to our own buffer queue. */ char *inbuf = NULL; if (!msgfilter || matchregex(channel->channelbuf, msgfilter) || matchregex(channel->channelbuf, stdfilter)) { inbuf = strdup(channel->channelbuf); } /* * Now we have safely stored the new message in our buffer. * Wait until any other clients on the same channel have picked up * this message (GOCLIENT reaches 0). * * We wrap this into an alarm handler, because it can occasionally * fail, causing the whole system to lock up. We dont want that.... * We'll set the alarm to trigger after 1 second. Experience shows * that we'll either succeed in a few milliseconds, or fail completely * and wait the full alarm-timer duration. */ gotalarm = 0; signal(SIGALRM, sig_handler); alarm(2); do { s.sem_num = GOCLIENT; s.sem_op = 0; s.sem_flg = 0; n = semop(channel->semid, &s, 1); } while ((n == -1) && (errno == EAGAIN) && running && (!gotalarm)); signal(SIGALRM, SIG_IGN); if (gotalarm) { errprintf("Gave up waiting for GOCLIENT to go low.\n"); } /* * Let master know we got it by downing BOARDBUSY. * This should not block, since BOARDBUSY is upped * by the master just before he ups GOCLIENT. */ do { s.sem_num = BOARDBUSY; s.sem_op = -1; s.sem_flg = IPC_NOWAIT; n = semop(channel->semid, &s, 1); } while ((n == -1) && (errno == EINTR)); if (n == -1) { errprintf("Tried to down BOARDBUSY: %s\n", strerror(errno)); } if (inbuf) { /* * See if they want us to rotate logs. We pass this on to * the worker module as well, but must handle our own logfile. */ if (strncmp(inbuf, "@@logrotate", 11) == 0) { freopen(logfn, "a", stdout); freopen(logfn, "a", stderr); } /* * Put the new message on our outbound queue. */ if (addmessage(inbuf) != 0) { /* Failed to queue message, free the buffer */ xfree(inbuf); } } } else { if (errno != EAGAIN) { dbgprintf("Semaphore wait aborted: %s\n", strerror(errno)); continue; } } /* * We've picked up messages from the master. Now we * must push them to the worker process. Since there * is no way to hang off both a semaphore and select(), * we'll just push as much data as possible into the * pipe. If we get to a point where we would block, * then wait a teeny bit of time and restart the * whole loop with checking for new messages from the * master etc. * * In theory, this could become an almost busy-wait loop. * In practice, however, the queue will be empty most * of the time because we'll just shove the data to the * worker child. */ for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) { int canwrite = 1, hasfailed = 0; xymon_peer_t *pwalk; time_t msgtimeout = gettimer() - MSGTIMEOUT; int flushcount = 0; pwalk = (xymon_peer_t *) gettreeitem(peers, handle); if (pwalk->msghead == NULL) continue; /* Ignore peers with nothing queued */ switch (pwalk->peerstatus) { case P_UP: canwrite = 1; break; case P_DOWN: openconnection(pwalk); canwrite = (pwalk->peerstatus == P_UP); break; case P_FAILED: canwrite = 0; break; } /* See if we have stale messages queued */ while (pwalk->msghead && (pwalk->msghead->tstamp < msgtimeout)) { flushmessage(pwalk); flushcount++; } if (flushcount) { errprintf("Flushed %d stale messages for %s:%d\n", flushcount, inet_ntoa(pwalk->peeraddr.sin_addr), ntohs(pwalk->peeraddr.sin_port)); } while (pwalk->msghead && canwrite) { fd_set fdwrite; struct timeval tmo; /* Check that this peer is ready for writing. */ FD_ZERO(&fdwrite); FD_SET(pwalk->peersocket, &fdwrite); tmo.tv_sec = 0; tmo.tv_usec = 2000; n = select(pwalk->peersocket+1, NULL, &fdwrite, NULL, &tmo); if (n == -1) { errprintf("select() failed: %s\n", strerror(errno)); canwrite = 0; hasfailed = 1; continue; } else if ((n == 0) || (!FD_ISSET(pwalk->peersocket, &fdwrite))) { canwrite = 0; continue; } n = write(pwalk->peersocket, pwalk->msghead->bufp, pwalk->msghead->buflen); if (n >= 0) { pwalk->msghead->bufp += n; pwalk->msghead->buflen -= n; if (pwalk->msghead->buflen == 0) flushmessage(pwalk); } else if (errno == EAGAIN) { /* * Write would block ... stop for now. */ canwrite = 0; } else { hasfailed = 1; } if (hasfailed) { /* Write failed, or message grew stale */ errprintf("Peer at %s:%d failed: %s\n", inet_ntoa(pwalk->peeraddr.sin_addr), ntohs(pwalk->peeraddr.sin_port), strerror(errno)); canwrite = 0; shutdownconnection(pwalk); if (pwalk->peertype == P_NET) locator_serverdown(pwalk->peername, locatorservice); pwalk->peerstatus = P_FAILED; } } } } /* Detach from channels */ close_channel(channel, CHAN_CLIENT); /* Close peer connections */ for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) { xymon_peer_t *pwalk = (xymon_peer_t *) gettreeitem(peers, handle); shutdownconnection(pwalk); } /* Remove the PID file */ if (pidfile) unlink(pidfile); return 0; }