📄 btd.c
字号:
local_bd[1], local_bd[2], local_bd[3], local_bd[4], local_bd[5]); opts[i++] = local_bd_str; opts[i++] = "remotebdaddr"; sprintf(remote_bd_str, "%02x:%02x:%02x:%02x:%02x:%02x", PEER(line).remote_bd[0], PEER(line).remote_bd[1], PEER(line).remote_bd[2], PEER(line).remote_bd[3], PEER(line).remote_bd[4], PEER(line).remote_bd[5]); opts[i++] = remote_bd_str; if (ipset->useradiusip) { opts[i++] = "useautoip"; } } else { opts[i++] = "noauth"; } if (ipset->proxyarp) { opts[i++] = "proxyarp"; /* ktune only works on pppd version > 2.3.10 */ /* similar as doing ' echo 1 > /proc/sys/net/ipv4/ip_forward */ opts[i++] = "ktune"; /* enables ip_forwarding */ } if (ipset->usingmasq) { pppd_options[i++] = "usingmasq"; } strcpy(local_ip, get_local_ip_address()); /* local/remote ip */ sprintf(ip_addresses, "%s:%s", local_ip, inet_ntoa(ipset->ip)); printf("IP used: %s\n", ip_addresses); opts[i++] = ip_addresses; /* DNS */ if (ipset->nbr_of_dns > 0) { /* at least one... */ opts[i++] = "ms-dns"; sprintf(ms_dns1, "%s", inet_ntoa(ipset->dns[0])); opts[i++] = ms_dns1; if (ipset->nbr_of_dns > 1) { opts[i++] = "ms-dns"; sprintf(ms_dns2, "%s", inet_ntoa(ipset->dns[1])); opts[i++] = ms_dns2; } } /* WINS */ if (ipset->nbr_of_wins > 0) { /* at least one... */ opts[i++] = "ms-wins"; sprintf(ms_wins1, "%s", inet_ntoa(ipset->wins[0])); opts[i++] = ms_wins1; if (ipset->nbr_of_wins > 1) { opts[i++] = "ms-wins"; sprintf(ms_wins2, "%s", inet_ntoa(ipset->wins[1])); opts[i++] = ms_wins2; } } /* Netmask */ opts[i++] = "netmask"; sprintf(netmask, "%s", inet_ntoa(ipset->netmask)); opts[i++] = netmask; } else { strcpy(local_ip, get_local_ip_address()); /* local IP */ sprintf(ip_addresses, "%s:", local_ip); /* Use /etc/ppp/options file for remote ppp settings. IPA is needed for correct multipoint setting or use a ppp options file for each ttyBT e.g options.ttyBT0, options.ttyBT1 which contains the remote IP address, dns, wins etc*/ syslog(LOG_INFO, "WARNING: No remote ip addr set, only local %s", ip_addresses); opts[i++] = ip_addresses; /* always do proxyarp */ opts[i++] = "proxyarp"; /* ktune only works on pppd version > 2.3.10 */ /* similar as doing ' echo 1 > /proc/sys/net/ipv4/ip_forward */ opts[i++] = "ktune"; /* enables ip_forwarding */ } /* end -- no ipa */ opts[i] = NULL; #if 0 /* print pppd_options */ i = 0; syslog(LOG_INFO, "pppd options used:"); while (opts[i]) syslog(LOG_INFO, "%s", opts[i++]);#endif}static int start_pppd(int line, char *speedstr, char **opts){ char dev[20]; sprintf(dev, "/dev/ttyBT%d",line); /* check state */ if (STATE(line) != PPPCONF_DONE) { syslog(LOG_INFO, "Warning: PPP config not done (%d)", STATE(line)); return -1; } if (PEER(line).do_modememul) { STATE(line) = MODEM_STARTED; /* run modem emulator in a child */ if (!(PEER(line).pppd_pid = vfork())) { /* replace first arg with MODEMEMULCMD (is handled by modem emulator) */ opts[0] = (char*)MODEMEMULCMD; execvp(MODEMEMULCMD, opts); fprintf(stderr, "%s: no such file or directory\n", MODEMEMULCMD); _exit(0); } else if (PEER(line).pppd_pid > 0) { syslog(LOG_INFO, "Started modem emulator on %s [pid: %d]", dev, PEER(line).pppd_pid); } } else { STATE(line) = PPPD_STARTED; if (!(PEER(line).pppd_pid = vfork())) { /* FIXME -- use opts inparam and not static opts */ execvp(PPPDCMD, opts); fprintf(stderr, "%s: no such file or directory\n", PPPDCMD); _exit(0); } else if (PEER(line).pppd_pid > 0) { D(syslog(LOG_INFO, "Started pppd on %s [pid: %d]", dev, PEER(line).pppd_pid)); } } return 0; }/* ============================================================= *//* Signal handler */static voidinit_sighandler(void){ struct sigaction act; D(syslog(LOG_INFO, "Initiating signal handler")); act.sa_handler = sighandler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGCHLD, &act, 0); /* Catches when pppd childs are done */ sigaction(SIGUSR1, &act, 0); /* Restart application */ sigaction(SIGUSR2, &act, 0); /* HW Upgrade ? */ sigaction(SIGTERM, &act, 0); /* Terminate application */}static voidsighandler(int sig){ D(syslog(LOG_INFO, "Sighandler got signal: %d", sig)); if (sig == SIGUSR1) { /* Shutdown all and restart */ btd_cleanup(); siglongjmp(jmpbuffer, 1); } else if (sig == SIGUSR2) /* ? */ { /* Close down phys dev, run hw_upgrade and restart btd */ // btd_cleanup(); /* FIXME -- execvp(hw_upgrade_prog) */ // siglongjmp(jmpbuffer, 1); } else if (sig == SIGTERM) { D(syslog(LOG_INFO, "Got SIGTERM, now exiting")); exit(0); } else if (sig == SIGCHLD) { int line = 0, pid, status; D(syslog(LOG_INFO, "One of the childs terminated")); /* Find pid for this child */ if ((pid = waitpid(-1, &status, WNOHANG)) <= 0) return; D(syslog(LOG_INFO, "pid %d terminated with status %d", pid, status)); /* find corresponding line */ while (line < BT_NBR_DATAPORTS) { D(syslog(LOG_INFO, "line %d pid: %d", line, PEER(line).pppd_pid)); if (PEER(line).pppd_pid == pid) { D(syslog(LOG_INFO, "line %d found", line)); break; } line++; } if (line == BT_NBR_DATAPORTS) { D(syslog(LOG_INFO, "Not a pppd pid")); return; } D(syslog(LOG_INFO, "PPP line %d was shutdown", line)); if (ipa_fd >= 0) { STATE(line) = WAITING_RETURN_PPPCONF; if (ipa_sendrequest(line, PEER(line).remote_bd, IPAREQ_RELEASEIPSET) < 0) { syslog(LOG_INFO, "IPA request failed or no IPA server"); /* put peer into state NOCONNECTION, if still connected this will be discovered in timout */ STATE(line) = NOCONNECTION; } } else { STATE(line) = NOCONNECTION; } PEER(line).ipset = NULL; PEER(line).pppd_pid = -1; return; }}/* ============================================================= *//* General BTD stuff */ static void init(){ int i; btd_pid = write_pidfile(PID_FILE); init_sighandler(); if ((sdpsrv_pid = start_sdp_server()) < 0) { perror("start_sdp_server"); exit(1); } for (i = 0; i < BT_NBR_DATAPORTS; i++) { PEER(i).state = NOCONNECTION; PEER(i).pppd_pid = -1; PEER(i).do_modememul = modem_emul; PEER(i).ipset = NULL; }#ifdef USE_IPASSIGN /* Look for IPA server */ ipa_fd = -1; i = 1; while (ipa_fd < 0) { ipa_fd = open_socket(IPASERVER, CLIENT); if (ipa_fd < 0) { D(syslog(LOG_INFO, "Found no IPA server")); if (i > 8) { break; } else { D(syslog(LOG_INFO, "Retrying in %d sec", i)); sleep(i); i *= 2; } } else { D(syslog(LOG_INFO, "Found IPA server")); } } #endif if (modem_emul == 1) D(syslog(LOG_INFO, "Using modem emulation")); else D(syslog(LOG_INFO, "Using NO modem emulation"));}static voidbtd_cleanup(void){ D(syslog(LOG_INFO, __FUNCTION__)); btd_killchilds(); printf("Shutting down Bluetooth stack\n"); shutdown_stack(bt_cfd); printf("Bluetooth stack shut down\n"); if (bt_cfd != -1) { close(bt_cfd); bt_cfd = -1; } /* now close phys device */ if (phys_fd != -1) { tcflush(phys_fd, TCIOFLUSH); close(phys_fd); phys_fd = -1; } if (ipa_fd != -1) { D(syslog(LOG_INFO, "Closing connection to IPA")); tcflush(ipa_fd, TCIOFLUSH); close(ipa_fd); ipa_fd = -1; } /* pid_fd is set if we created the pid file when we started */ if (btd_pid != -1) { unlink(PID_FILE); }}static voidbtd_killchilds(void){ int line; if (sdpsrv_pid > 0) { D(syslog(LOG_INFO, "Killing SDP server")); kill(sdpsrv_pid, SIGTERM); if (waitpid(sdpsrv_pid, NULL, 0) < 0) perror("waitpid sdp server"); sdpsrv_pid = 0; } /* Kill all pppd:s */ for (line = 0; line < BT_NBR_DATAPORTS; line++) { if (STATE(line) == PPPD_STARTED) { D(syslog(LOG_INFO, "Killing pppd on line %d", line)); kill(PEER(line).pppd_pid, SIGTERM); if (waitpid(PEER(line).pppd_pid, NULL, 0) < 0) perror("waitpid pppd"); PEER(line).pppd_pid = 0; } }}/* ========================================================== *//* IPA stuff */static int ipa_sendrequest(int line, unsigned char *bd, unsigned short type){ unsigned char buf[IPA_MSG_MAXSIZE]; struct ipa_msg *msg; struct ipa_request *req; D(syslog(LOG_INFO, __FUNCTION__ ": Type %d", type)); msg = (struct ipa_msg*)buf; msg->type = type; msg->len = sizeof(struct ipa_request); req = (struct ipa_request*)msg->msg; req->id = line; memcpy(req->remote_bd, bd, 6); return ipa_write(ipa_fd, msg);}static int parse_ipa_response(struct ipa_msg *msg){ switch (msg->type) { case IPARSP_STATUS: { ipa_status *rsp = (struct ipa_status*)msg->msg; D(syslog(LOG_INFO, __FUNCTION__ ": Got status %d on line %d", rsp->status, rsp->id)); /* Check state */ if (STATE(rsp->id) != WAITING_RETURN_PPPCONF) { syslog(LOG_INFO, __FUNCTION__ ": Wrong state (case IPARSP_STATUS)"); return -ERR_WRONGSTATE; } /* Check status */ if (rsp->status == IPA_STATUSFAILED) { syslog(LOG_INFO, __FUNCTION__ ": Request failed [line:%d]", rsp->id); return -IPA_STATUSFAILED; } else D(syslog(LOG_INFO, __FUNCTION__ ": Request succeeded [line:%d]", rsp->id)); /* put peer into NOCONNECTION, if still connected this will be discovered from timeout */ STATE(rsp->id) = NOCONNECTION; return 0; } case IPARSP_PEERSETTINGS: { ipa_response* rsp = (struct ipa_response*)msg->msg; D(syslog(LOG_INFO, __FUNCTION__ ": Got client settings")); /* Check state */ if (STATE(rsp->id) != WAITING_PPPCONF) { syslog(LOG_INFO, __FUNCTION__ ": Wrong state case (IPARSP_PEERSETTINGS)"); return -ERR_WRONGSTATE; } /* Check status */ if (rsp->status == IPA_STATUSFAILED) { /* error */ syslog(LOG_INFO, __FUNCTION__ ": Failed to get client settings\n"); return -ERR_REQUESTFAILED; } /* Store ipa settings in peer struct */ memcpy(PEER(rsp->id).ipset, &rsp->set, msg->len); PEER(rsp->id).state = PPPCONF_DONE; /* Build options and start ppp */ build_pppdopts(rsp->id, (char**)pppd_options); start_pppd(rsp->id, speedstr, (char**)pppd_options); return 0; } default: syslog(LOG_INFO, __FUNCTION__ ": Unknown message type"); break; } return 0;}/* ============================================================= */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -