static void cmd_init(struct http_channel *c) { struct http_request *r = c->request; const char *clear = http_argbyname(r, "clear"); const char *content_type = http_lookup_header(r->headers, "Content-Type"); unsigned int sesid; struct http_session *s; struct http_response *rs = c->response; struct conf_service *service = 0; /* no service (yet) */ if (r->content_len && content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) { xmlDoc *doc = xmlParseMemory(r->content_buf, r->content_len); xmlNode *root_n; if (!doc) { error(rs, PAZPAR2_MALFORMED_SETTING, 0); return; } root_n = xmlDocGetRootElement(doc); service = service_create(c->server, root_n); xmlFreeDoc(doc); if (!service) { error(rs, PAZPAR2_MALFORMED_SETTING, 0); return; } } if (!service) { const char *service_name = http_argbyname(c->request, "service"); service = locate_service(c->server, service_name); if (!service) { error(rs, PAZPAR2_NO_SERVICE, service_name ? service_name : "unnamed"); return; } } sesid = make_sessionid(); s = http_session_create(service, c->http_sessions, sesid); yaz_log(c->http_sessions->log_level, "Session init %u ", sesid); if (!clear || *clear == '0') session_init_databases(s->psession); else yaz_log(YLOG_LOG, "Session %u init: No databases preloaded", sesid); if (process_settings(s->psession, c->request, c->response) < 0) return; response_open(c, "init"); wrbuf_printf(c->wrbuf, "<session>%d", sesid); if (c->server->server_id) { wrbuf_puts(c->wrbuf, "."); wrbuf_puts(c->wrbuf, c->server->server_id); } wrbuf_puts(c->wrbuf, "</session>" "<protocol>" PAZPAR2_PROTOCOL_VERSION "</protocol>"); wrbuf_printf(c->wrbuf, "<keepAlive>%d</keepAlive>\n", 1000 * ((s->psession->service->session_timeout >= 20) ? (s->psession->service->session_timeout - 10) : 50)); response_close(c, "init"); }
/* * Dispatch a message from the tunnel driver. It could be an actual * PPPoE message or just an event notification. */ static void handle_input(uint32_t *ctrlbuf, int ctrllen, uint32_t *databuf, int datalen) { poep_t *poep = (poep_t *)databuf; union ppptun_name ptn; int retv; struct strbuf ctrl; struct strbuf data; void *srvp; boolean_t launch; struct ppptun_control *ptc; if (ctrllen != sizeof (*ptc)) { logdbg("bogus %d byte control message from driver", ctrllen); return; } ptc = (struct ppptun_control *)ctrlbuf; /* Switch out on event notifications. */ switch (ptc->ptc_action) { case PTCA_TEST: logdbg("test reply for discriminator %X", ptc->ptc_discrim); return; case PTCA_CONTROL: break; case PTCA_DISCONNECT: logdbg("session %d disconnected on %s; send PADT", ptc->ptc_rsessid, ptc->ptc_name); poep = poe_mkheader(pkt_output, POECODE_PADT, ptc->ptc_rsessid); ptc->ptc_action = PTCA_CONTROL; ctrl.len = sizeof (*ptc); ctrl.buf = (caddr_t)ptc; data.len = poe_length(poep) + sizeof (*poep); data.buf = (caddr_t)poep; if (putmsg(tunfd, &ctrl, &data, 0) < 0) { logerr("putmsg PADT: %s", mystrerror(errno)); } else { output_packets++; } return; case PTCA_UNPLUMB: logdbg("%s unplumbed", ptc->ptc_name); return; default: logdbg("unexpected code %d from driver", ptc->ptc_action); return; } /* Only PPPoE control messages get here. */ input_packets++; if (datalen < sizeof (*poep)) { logdbg("incomplete PPPoE message from %s/%s", ehost(&ptc->ptc_address), ptc->ptc_name); return; } /* Server handles only PADI and PADR; all others are ignored. */ if (poep->poep_code == POECODE_PADI) { padi_packets++; } else if (poep->poep_code == POECODE_PADR) { padr_packets++; } else { loginfo("unexpected %s from %s", poe_codename(poep->poep_code), ehost(&ptc->ptc_address)); return; } logdbg("Recv from %s/%s: %s", ehost(&ptc->ptc_address), ptc->ptc_name, poe_codename(poep->poep_code)); /* Parse out service and formulate template reply. */ retv = locate_service(poep, datalen, ptc->ptc_name, &ptc->ptc_address, pkt_output, &srvp); /* Continue formulating reply */ launch = B_FALSE; if (retv != 1) { /* Ignore initiation if we don't offer a service. */ if (retv <= 0 && poep->poep_code == POECODE_PADI) { logdbg("no services; no reply"); return; } if (retv == 0) (void) poe_add_str((poep_t *)pkt_output, POETT_NAMERR, "No such service."); } else { /* Exactly one service chosen; if it's PADR, then we start. */ if (poep->poep_code == POECODE_PADR) { launch = B_TRUE; } } poep = (poep_t *)pkt_output; /* Select control interface for output. */ (void) strncpy(ptn.ptn_name, ptc->ptc_name, sizeof (ptn.ptn_name)); if (strioctl(tunfd, PPPTUN_SCTL, &ptn, sizeof (ptn), 0) < 0) { logerr("PPPTUN_SCTL %s: %s", ptn.ptn_name, mystrerror(errno)); return; } /* Launch the PPP service */ if (launch && launch_service(tunfd, poep, srvp, ptc)) sessions_started++; /* Send the reply. */ ctrl.len = sizeof (*ptc); ctrl.buf = (caddr_t)ptc; data.len = poe_length(poep) + sizeof (*poep); data.buf = (caddr_t)poep; if (putmsg(tunfd, &ctrl, &data, 0) < 0) { logerr("putmsg %s: %s", ptc->ptc_name, mystrerror(errno)); } else { output_packets++; logdbg("Send to %s/%s: %s", ehost(&ptc->ptc_address), ptc->ptc_name, poe_codename(poep->poep_code)); } }