Use picotcp for ppp protocol processing. Now all is needed is a tap or
tun interface.
This commit is contained in:
parent
ce3d8f2baa
commit
6699a8a294
|
@ -436,10 +436,11 @@ static int pico_arp_process_in(struct pico_frame *f, struct pico_arp_hdr *hdr, s
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pico_arp_check_flooding(f, me) < 0) {
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
// FIXME Problem with proxy ARP
|
||||
// if (pico_arp_check_flooding(f, me) < 0) {
|
||||
// pico_frame_discard(f);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
/* If no existing entry was found, create a new entry, or fail trying. */
|
||||
if ((!found) && (pico_arp_create_entry(hdr->s_mac, hdr->src, f->dev) < 0)) {
|
||||
|
|
|
@ -282,6 +282,7 @@ struct pico_device_ppp {
|
|||
uint8_t frame_id;
|
||||
uint8_t timer_on;
|
||||
uint16_t mru;
|
||||
uint32_t ipcp_peer_ip;
|
||||
};
|
||||
|
||||
|
||||
|
@ -513,7 +514,7 @@ static int pico_ppp_send(struct pico_device *dev, void *buf, int len)
|
|||
int fcs_start;
|
||||
int i = 0;
|
||||
|
||||
ppp_dbg(" >>>>>>>>> PPP OUT\n");
|
||||
ppp_dbg(" >>>>>>>>> PPP OUT len %d\n", len);
|
||||
|
||||
if (ppp->ipcp_state != PPP_IPCP_STATE_OPENED)
|
||||
return len;
|
||||
|
@ -1141,12 +1142,12 @@ static inline uint32_t ipcp_request_options_size(struct pico_device_ppp *ppp)
|
|||
{
|
||||
uint32_t size = 0;
|
||||
|
||||
/* if (ppp->ipcp_ip) */
|
||||
size += IPCP_ADDR_LEN;
|
||||
/* if (ppp->ipcp_dns1) */
|
||||
size += IPCP_ADDR_LEN;
|
||||
/* if (ppp->ipcp_dns2) */
|
||||
size += IPCP_ADDR_LEN;
|
||||
if (ppp->ipcp_peer_ip)
|
||||
size += IPCP_ADDR_LEN;
|
||||
if (ppp->ipcp_dns1)
|
||||
size += IPCP_ADDR_LEN;
|
||||
if (ppp->ipcp_dns2)
|
||||
size += IPCP_ADDR_LEN;
|
||||
if (ppp->ipcp_nbns1)
|
||||
size += IPCP_ADDR_LEN;
|
||||
|
||||
|
@ -1171,7 +1172,7 @@ static int ipcp_request_add_address(uint8_t *dst, uint8_t tag, uint32_t arg)
|
|||
static void ipcp_request_fill(struct pico_device_ppp *ppp, uint8_t *opts)
|
||||
{
|
||||
if (ppp->ipcp_allowed_fields & IPCP_ALLOW_IP)
|
||||
opts += ipcp_request_add_address(opts, IPCP_OPT_IP, ppp->ipcp_ip);
|
||||
opts += ipcp_request_add_address(opts, IPCP_OPT_IP, ppp->ipcp_peer_ip);
|
||||
|
||||
if (ppp->ipcp_allowed_fields & IPCP_ALLOW_DNS1)
|
||||
opts += ipcp_request_add_address(opts, IPCP_OPT_DNS1, ppp->ipcp_dns1);
|
||||
|
@ -1216,12 +1217,16 @@ static void ipcp_reject_vj(struct pico_device_ppp *ppp, uint8_t *comp_req)
|
|||
struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *) (ipcp_req + prefix);
|
||||
uint8_t *p = ipcp_req + prefix + sizeof(struct pico_ipcp_hdr);
|
||||
uint32_t i;
|
||||
uint8_t *p2 = comp_req + sizeof(struct pico_ipcp_hdr);
|
||||
|
||||
ih->id = ppp->frame_id++;
|
||||
ih->code = PICO_CONF_REQ;
|
||||
ih->id = ((struct pico_ipcp_hdr *)comp_req)->id;
|
||||
ih->code = PICO_CONF_REJ;
|
||||
ih->len = short_be(IPCP_VJ_LEN + sizeof(struct pico_ipcp_hdr));
|
||||
for(i = 0; i < IPCP_OPT_VJ; i++)
|
||||
p[i] = comp_req[i + sizeof(struct pico_ipcp_hdr)];
|
||||
|
||||
while (p2[0] != IPCP_OPT_VJ)
|
||||
p2 += p2[1];
|
||||
for(i = 0; i < IPCP_VJ_LEN; i++)
|
||||
p[i] = p2[i];
|
||||
ppp_dbg("Sending IPCP CONF REJ VJ\n");
|
||||
pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_IPCP,
|
||||
ipcp_req, /* Start of PPP packet */
|
||||
|
@ -1243,9 +1248,10 @@ static void ppp_ipv4_conf(struct pico_device_ppp *ppp)
|
|||
0
|
||||
};
|
||||
ip.addr = ppp->ipcp_ip;
|
||||
nm.addr = 0xFFFFFF00;
|
||||
nm.addr = 0xFFFFFFFF;
|
||||
pico_ipv4_link_add(&ppp->dev, ip, nm);
|
||||
pico_ipv4_route_add(any, any, any, 1, pico_ipv4_link_by_dev(&ppp->dev));
|
||||
ip.addr = ppp->ipcp_peer_ip;
|
||||
pico_ipv4_route_add(ip, nm, any, 1, pico_ipv4_link_by_dev(&ppp->dev));
|
||||
|
||||
dns1.addr = ppp->ipcp_dns1;
|
||||
dns2.addr = ppp->ipcp_dns2;
|
||||
|
@ -1253,12 +1259,14 @@ static void ppp_ipv4_conf(struct pico_device_ppp *ppp)
|
|||
pico_dns_client_nameserver(&dns2, PICO_DNS_NS_ADD);
|
||||
}
|
||||
|
||||
static void ipcp_send_nack(struct pico_device_ppp *ppp);
|
||||
|
||||
static void ipcp_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
|
||||
{
|
||||
struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *)pkt;
|
||||
uint8_t *p = pkt + sizeof(struct pico_ipcp_hdr);
|
||||
int reject = 0;
|
||||
int nak = 0;
|
||||
while (p < pkt + len) {
|
||||
if (p[0] == IPCP_OPT_VJ) {
|
||||
reject++;
|
||||
|
@ -1266,75 +1274,72 @@ static void ipcp_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t
|
|||
|
||||
if (p[0] == IPCP_OPT_IP) {
|
||||
if (ih->code != PICO_CONF_REJ)
|
||||
ppp->ipcp_ip = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
else {
|
||||
ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_IP);
|
||||
ppp->ipcp_ip = 0;
|
||||
{
|
||||
uint32_t ipcp_ip = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
if (ipcp_ip != ppp->ipcp_peer_ip)
|
||||
nak++;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[0] == IPCP_OPT_DNS1) {
|
||||
if (ih->code != PICO_CONF_REJ)
|
||||
ppp->ipcp_dns1 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
else {
|
||||
ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_DNS1);
|
||||
ppp->ipcp_dns1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[0] == IPCP_OPT_NBNS1) {
|
||||
if (ih->code != PICO_CONF_REJ)
|
||||
ppp->ipcp_nbns1 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
else {
|
||||
ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_NBNS1);
|
||||
ppp->ipcp_nbns1 = 0;
|
||||
{
|
||||
uint32_t ipcp_dns1 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
if (ipcp_dns1 != ppp->ipcp_dns1)
|
||||
nak++;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[0] == IPCP_OPT_DNS2) {
|
||||
if (ih->code != PICO_CONF_REJ)
|
||||
ppp->ipcp_dns2 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
else {
|
||||
ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_DNS2);
|
||||
ppp->ipcp_dns2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[0] == IPCP_OPT_NBNS2) {
|
||||
if (ih->code != PICO_CONF_REJ)
|
||||
ppp->ipcp_nbns2 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
else {
|
||||
ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_NBNS2);
|
||||
ppp->ipcp_nbns2 = 0;
|
||||
{
|
||||
uint32_t ipcp_dns2 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
|
||||
if (ipcp_dns2 != ppp->ipcp_dns2)
|
||||
nak++;
|
||||
}
|
||||
}
|
||||
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
switch(ih->code) {
|
||||
case PICO_CONF_ACK:
|
||||
ppp_dbg("Received IPCP CONF ACK\n");
|
||||
break;
|
||||
case PICO_CONF_REQ:
|
||||
ppp_dbg("Received IPCP CONF REQ\n");
|
||||
break;
|
||||
case PICO_CONF_NAK:
|
||||
ppp_dbg("Received IPCP CONF NAK\n");
|
||||
break;
|
||||
case PICO_CONF_REJ:
|
||||
ppp_dbg("Received IPCP CONF REJ\n");
|
||||
break;
|
||||
}
|
||||
if (reject) {
|
||||
ipcp_reject_vj(ppp, p);
|
||||
ipcp_reject_vj(ppp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
ppp->pkt = pkt;
|
||||
ppp->len = len;
|
||||
|
||||
if (nak) {
|
||||
ipcp_send_nack(ppp);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ih->code) {
|
||||
case PICO_CONF_ACK:
|
||||
ppp_dbg("Received IPCP CONF ACK\n");
|
||||
evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCA);
|
||||
break;
|
||||
case PICO_CONF_REQ:
|
||||
ppp_dbg("Received IPCP CONF REQ\n");
|
||||
evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCR_POS);
|
||||
break;
|
||||
case PICO_CONF_NAK:
|
||||
ppp_dbg("Received IPCP CONF NAK\n");
|
||||
evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCN);
|
||||
break;
|
||||
case PICO_CONF_REJ:
|
||||
ppp_dbg("Received IPCP CONF REJ\n");
|
||||
|
||||
evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCN);
|
||||
break;
|
||||
}
|
||||
|
@ -1923,9 +1928,61 @@ static void evaluate_auth_state(struct pico_device_ppp *ppp, enum ppp_auth_event
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ipcp_nack_options_size(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
|
||||
{
|
||||
uint8_t *p = pkt + sizeof(struct pico_ipcp_hdr);
|
||||
uint32_t size = 0;
|
||||
|
||||
IGNORE_PARAMETER(ppp);
|
||||
|
||||
while (p < pkt + len) {
|
||||
if (p[0] == IPCP_OPT_IP)
|
||||
size += IPCP_ADDR_LEN;
|
||||
else if (p[0] == IPCP_OPT_DNS1)
|
||||
size += IPCP_ADDR_LEN;
|
||||
else if (p[0] == IPCP_OPT_DNS2)
|
||||
size += IPCP_ADDR_LEN;
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void ipcp_send_nack(struct pico_device_ppp *ppp)
|
||||
{
|
||||
IGNORE_PARAMETER(ppp);
|
||||
uint8_t *pkt = ppp->pkt;
|
||||
uint32_t len = ppp->len;
|
||||
|
||||
uint8_t ipcp_req[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_ipcp_hdr) + ipcp_nack_options_size(ppp, pkt, len) + PPP_FCS_SIZE + 1];
|
||||
uint32_t prefix = PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE;
|
||||
struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *) (ipcp_req + prefix);
|
||||
uint8_t *p = ipcp_req + prefix + sizeof(struct pico_ipcp_hdr);
|
||||
uint8_t *preq = pkt + sizeof(struct pico_ipcp_hdr);
|
||||
|
||||
ih->id = ((struct pico_ipcp_hdr *)pkt)->id;
|
||||
ih->code = PICO_CONF_NAK;
|
||||
ih->len = short_be((uint16_t)(ipcp_nack_options_size(ppp, pkt, len) + sizeof(struct pico_ipcp_hdr)));
|
||||
|
||||
while (preq < pkt + len) {
|
||||
if (preq[0] == IPCP_OPT_IP)
|
||||
{
|
||||
p += ipcp_request_add_address(p, IPCP_OPT_IP, ppp->ipcp_peer_ip);
|
||||
}
|
||||
else if (preq[0] == IPCP_OPT_DNS1)
|
||||
{
|
||||
p += ipcp_request_add_address(p, IPCP_OPT_DNS1, ppp->ipcp_dns1);
|
||||
}
|
||||
else if (preq[0] == IPCP_OPT_DNS2)
|
||||
{
|
||||
p += ipcp_request_add_address(p, IPCP_OPT_DNS2, ppp->ipcp_dns2);
|
||||
}
|
||||
preq += preq[1];
|
||||
}
|
||||
|
||||
ppp_dbg("Sending IPCP CONF NAK\n");
|
||||
pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_IPCP,
|
||||
ipcp_req, /* Start of PPP packet */
|
||||
(uint32_t)sizeof(ipcp_req));
|
||||
}
|
||||
|
||||
static void ipcp_bring_up(struct pico_device_ppp *ppp)
|
||||
|
@ -1934,10 +1991,10 @@ static void ipcp_bring_up(struct pico_device_ppp *ppp)
|
|||
|
||||
if (ppp->ipcp_ip) {
|
||||
char my_ip[16], my_dns[16];
|
||||
pico_ipv4_to_string(my_ip, ppp->ipcp_ip);
|
||||
ppp_dbg("Received IP config %s\n", my_ip);
|
||||
pico_ipv4_to_string(my_ip, ppp->ipcp_peer_ip);
|
||||
ppp_dbg("Assigned IP to peer: %s\n", my_ip);
|
||||
pico_ipv4_to_string(my_dns, ppp->ipcp_dns1);
|
||||
ppp_dbg("Received DNS: %s\n", my_dns);
|
||||
ppp_dbg("Assigned DNS: %s\n", my_dns);
|
||||
ppp_ipv4_conf(ppp);
|
||||
}
|
||||
}
|
||||
|
@ -2195,7 +2252,7 @@ struct pico_device *pico_ppp_create(void)
|
|||
ppp->dev.link_state = pico_ppp_link_state;
|
||||
ppp->frame_id = (uint8_t)(pico_rand() % 0xFF);
|
||||
|
||||
ppp->modem_state = PPP_MODEM_STATE_INITIAL;
|
||||
ppp->modem_state = PPP_MODEM_STATE_CONNECTED;
|
||||
ppp->lcp_state = PPP_LCP_STATE_INITIAL;
|
||||
ppp->auth_state = PPP_AUTH_STATE_INITIAL;
|
||||
ppp->ipcp_state = PPP_IPCP_STATE_INITIAL;
|
||||
|
@ -2209,7 +2266,7 @@ struct pico_device *pico_ppp_create(void)
|
|||
ppp->mru = PICO_PPP_MRU;
|
||||
|
||||
LCPOPT_SET_LOCAL(ppp, LCPOPT_MRU);
|
||||
LCPOPT_SET_LOCAL(ppp, LCPOPT_AUTH); /* We support authentication, even if it's not part of the req */
|
||||
//LCPOPT_SET_LOCAL(ppp, LCPOPT_AUTH); /* We support authentication, even if it's not part of the req */
|
||||
LCPOPT_SET_LOCAL(ppp, LCPOPT_PROTO_COMP);
|
||||
LCPOPT_SET_LOCAL(ppp, LCPOPT_ADDRCTL_COMP);
|
||||
|
||||
|
@ -2221,7 +2278,9 @@ struct pico_device *pico_ppp_create(void)
|
|||
int pico_ppp_connect(struct pico_device *dev)
|
||||
{
|
||||
struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
|
||||
ppp->autoreconnect = 1;
|
||||
ppp_modem_connected(ppp);
|
||||
evaluate_lcp_state(ppp, PPP_LCP_EVENT_OPEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2310,3 +2369,47 @@ int pico_ppp_set_password(struct pico_device *dev, const char *password)
|
|||
strncpy(ppp->password, password, sizeof(ppp->password) - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_ppp_set_ip(struct pico_device *dev, struct pico_ip4 ip)
|
||||
{
|
||||
struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
ppp->ipcp_ip = ip.addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_ppp_set_dns1(struct pico_device *dev, struct pico_ip4 ip)
|
||||
{
|
||||
struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
ppp->ipcp_dns1 = ip.addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_ppp_set_dns2(struct pico_device *dev, struct pico_ip4 ip)
|
||||
{
|
||||
struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
ppp->ipcp_dns2 = ip.addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_ppp_set_peer_ip(struct pico_device *dev, struct pico_ip4 ip)
|
||||
{
|
||||
struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
ppp->ipcp_peer_ip = ip.addr;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,5 +22,9 @@ int pico_ppp_set_serial_set_speed(struct pico_device *dev, int (*sspeed)(struct
|
|||
int pico_ppp_set_apn(struct pico_device *dev, const char *apn);
|
||||
int pico_ppp_set_username(struct pico_device *dev, const char *username);
|
||||
int pico_ppp_set_password(struct pico_device *dev, const char *password);
|
||||
int pico_ppp_set_ip(struct pico_device *dev, struct pico_ip4 ip);
|
||||
int pico_ppp_set_dns1(struct pico_device *dev, struct pico_ip4 ip);
|
||||
int pico_ppp_set_dns2(struct pico_device *dev, struct pico_ip4 ip);
|
||||
int pico_ppp_set_peer_ip(struct pico_device *dev, struct pico_ip4 ip);
|
||||
|
||||
#endif /* INCLUDE_PICO_PPP */
|
||||
|
|
|
@ -89,7 +89,7 @@ void pico_tap_destroy(struct pico_device *dev)
|
|||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static int tap_open(char *name)
|
||||
static int tap_open(const char *name)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int tap_fd;
|
||||
|
@ -107,7 +107,7 @@ static int tap_open(char *name)
|
|||
return tap_fd;
|
||||
}
|
||||
#else
|
||||
static int tap_open(char *name)
|
||||
static int tap_open(const char *name)
|
||||
{
|
||||
int tap_fd;
|
||||
(void)name;
|
||||
|
@ -118,7 +118,7 @@ static int tap_open(char *name)
|
|||
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static int tap_get_mac(char *name, uint8_t *mac)
|
||||
static int tap_get_mac(const char *name, uint8_t *mac)
|
||||
{
|
||||
int sck;
|
||||
struct ifreq eth;
|
||||
|
@ -146,7 +146,7 @@ static int tap_get_mac(char *name, uint8_t *mac)
|
|||
#include <net/if_dl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if_types.h>
|
||||
static int tap_get_mac(char *name, uint8_t *mac)
|
||||
static int tap_get_mac(const char *name, uint8_t *mac)
|
||||
{
|
||||
struct sockaddr_dl *sdl;
|
||||
struct ifaddrs *ifap, *root;
|
||||
|
@ -172,7 +172,7 @@ static int tap_get_mac(char *name, uint8_t *mac)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct pico_device *pico_tap_create(char *name)
|
||||
struct pico_device *pico_tap_create(const char *name)
|
||||
{
|
||||
struct pico_device_tap *tap = PICO_ZALLOC(sizeof(struct pico_device_tap));
|
||||
uint8_t mac[6] = {};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "pico_device.h"
|
||||
|
||||
void pico_tap_destroy(struct pico_device *tap);
|
||||
struct pico_device *pico_tap_create(char *name);
|
||||
struct pico_device *pico_tap_create(const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ void pico_tun_destroy(struct pico_device *dev)
|
|||
}
|
||||
|
||||
|
||||
static int tun_open(char *name)
|
||||
static int tun_open(const char *name)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int tun_fd;
|
||||
|
@ -80,7 +80,7 @@ static int tun_open(char *name)
|
|||
|
||||
|
||||
|
||||
struct pico_device *pico_tun_create(char *name)
|
||||
struct pico_device *pico_tun_create(const char *name)
|
||||
{
|
||||
struct pico_device_tun *tun = PICO_ZALLOC(sizeof(struct pico_device_tun));
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "pico_device.h"
|
||||
|
||||
void pico_tun_destroy(struct pico_device *tun);
|
||||
struct pico_device *pico_tun_create(char *name);
|
||||
struct pico_device *pico_tun_create(const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1575,8 +1575,9 @@ static int pico_ipv4_pre_forward_checks(struct pico_frame *f)
|
|||
|
||||
static int pico_ipv4_forward_check_dev(struct pico_frame *f)
|
||||
{
|
||||
if (f->dev->eth != NULL)
|
||||
f->len -= PICO_SIZE_ETHHDR;
|
||||
// TODO What was this for? Clearly causing problems with tap
|
||||
// if (f->dev->eth != NULL)
|
||||
// f->len -= PICO_SIZE_ETHHDR;
|
||||
|
||||
if (f->len > f->dev->mtu) {
|
||||
pico_notify_pkt_too_big(f);
|
||||
|
|
|
@ -26,8 +26,15 @@
|
|||
#include "hw/holly/holly_intc.h"
|
||||
#include "hw/sh4/sh4_sched.h"
|
||||
#include "oslib/oslib.h"
|
||||
#include "picoppp.h"
|
||||
#include "pppd.h"
|
||||
|
||||
#define start_pppd start_pico
|
||||
#define stop_pppd stop_pico
|
||||
#define write_pppd write_pico
|
||||
#define read_pppd read_pico
|
||||
|
||||
|
||||
#define MODEM_COUNTRY_RES 0
|
||||
#define MODEM_COUNTRY_JAP 1
|
||||
#define MODEM_COUNTRY_USA 2
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
#include <queue>
|
||||
|
||||
extern "C" {
|
||||
#include <pico_stack.h>
|
||||
#include <pico_dev_ppp.h>
|
||||
#include <pico_dev_tap.h>
|
||||
#include <pico_arp.h>
|
||||
#include <pico_dev_tun.h>
|
||||
#ifdef DHCP
|
||||
#include <pico_dhcp_client.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
#define NETWORK_TUN
|
||||
|
||||
#include "types.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "picoppp.h"
|
||||
|
||||
static struct pico_device *ppp;
|
||||
struct pico_device* tap;
|
||||
struct pico_device* tun;
|
||||
|
||||
static std::queue<u8> in_buffer;
|
||||
static std::queue<u8> out_buffer;
|
||||
|
||||
static int modem_read(struct pico_device *dev, void *data, int len)
|
||||
{
|
||||
u8 *p = (u8 *)data;
|
||||
|
||||
int count = 0;
|
||||
while (!out_buffer.empty() && count < len)
|
||||
{
|
||||
*p++ = out_buffer.front();
|
||||
out_buffer.pop();
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int modem_write(struct pico_device *dev, const void *data, int len)
|
||||
{
|
||||
u8 *p = (u8 *)data;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
in_buffer.push(*p++);
|
||||
len--;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void write_pico(u8 b)
|
||||
{
|
||||
out_buffer.push(b);
|
||||
}
|
||||
|
||||
int read_pico()
|
||||
{
|
||||
pico_stack_tick();
|
||||
|
||||
if (in_buffer.empty())
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
u32 b = in_buffer.front();
|
||||
in_buffer.pop();
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
static int modem_set_speed(struct pico_device *dev, uint32_t speed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DHCP
|
||||
static uint32_t dhcpclient_xid;
|
||||
static struct pico_ip4 dchp_address = { 0 };
|
||||
|
||||
void callback_dhcpclient(void *arg, int code)
|
||||
{
|
||||
char s_address[16] = { }, s_gateway[16] = { };
|
||||
|
||||
printf("DHCP client: callback happened with code %d!\n", code);
|
||||
if (code == PICO_DHCP_SUCCESS)
|
||||
{
|
||||
dchp_address = pico_dhcp_get_address(arg);
|
||||
//gateway = pico_dhcp_get_gateway(arg);
|
||||
pico_ipv4_to_string(s_address, dchp_address.addr);
|
||||
//pico_ipv4_to_string(s_gateway, gateway.addr);
|
||||
printf("DHCP client: got IP %s assigned with cli %p\n", s_address, arg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool pico_stack_inited;
|
||||
|
||||
bool start_pico()
|
||||
{
|
||||
struct pico_ip4 ipaddr, netmask, zero = {
|
||||
0
|
||||
};
|
||||
|
||||
if (!pico_stack_inited)
|
||||
{
|
||||
pico_stack_init();
|
||||
pico_stack_inited = true;
|
||||
}
|
||||
|
||||
// PPP
|
||||
ppp = pico_ppp_create();
|
||||
if (!ppp)
|
||||
return false;
|
||||
string dc_ip = cfgLoadStr("network", "IP", "");
|
||||
if (dc_ip.length() == 0)
|
||||
{
|
||||
printf("No IP address set for Netplay. Set IP= in the [network] section\n");
|
||||
return false;
|
||||
}
|
||||
pico_string_to_ipv4(dc_ip.c_str(), &ipaddr.addr);
|
||||
pico_ppp_set_peer_ip(ppp, ipaddr);
|
||||
pico_string_to_ipv4("192.168.167.1", &ipaddr.addr);
|
||||
pico_ppp_set_ip(ppp, ipaddr);
|
||||
|
||||
string dns_ip = cfgLoadStr("network", "DNS", "46.101.91.123");
|
||||
pico_string_to_ipv4(dns_ip.c_str(), &ipaddr.addr);
|
||||
pico_ppp_set_dns1(ppp, ipaddr);
|
||||
|
||||
#ifdef NETWORK_TAP
|
||||
// TAP
|
||||
// tap config:
|
||||
// # ip tuntap add mode tap user joe
|
||||
// # ifconfig tap0 192.168.5.5
|
||||
// # ip link set tap0 up
|
||||
// # ip route add <IP>/32 dev tap0 # where <IP> is the value of network:IP in emu.cfg./. This also allows proxy arp
|
||||
// # echo '1' >/proc/sys/net/ipv4/conf/all/proxy_arp
|
||||
// (or ...conf/tap0/proxy_arp and ...conf/eth0/proxy_arp only)
|
||||
tap = pico_tap_create("tap0");
|
||||
if (!tap)
|
||||
{
|
||||
stop_pico();
|
||||
return false;
|
||||
}
|
||||
|
||||
pico_string_to_ipv4("192.168.166.2", &ipaddr.addr);
|
||||
pico_string_to_ipv4("255.255.255.0", &netmask.addr);
|
||||
pico_ipv4_link_add(tap, ipaddr, netmask);
|
||||
// Proxy ARP
|
||||
pico_arp_create_entry(tap->eth->mac.addr, ipaddr, ppp);
|
||||
#endif
|
||||
|
||||
#ifdef NETWORK_TUN
|
||||
// TUN
|
||||
// tun config:
|
||||
// # ip tuntap add mode tun user joe
|
||||
// # ip link set tun0 up
|
||||
// # ip route add <IP>/32 dev tun0 # where <IP> is the value of network:IP in emu.cfg./. This also allows proxy arp
|
||||
// # echo '1' >/proc/sys/net/ipv4/conf/all/proxy_arp
|
||||
// (or ...conf/tun0/proxy_arp and ...conf/eth0/proxy_arp only)
|
||||
tun = pico_tun_create("tun0");
|
||||
if (!tun)
|
||||
{
|
||||
stop_pico();
|
||||
return false;
|
||||
}
|
||||
|
||||
pico_string_to_ipv4("192.168.166.1", &ipaddr.addr);
|
||||
pico_string_to_ipv4("255.255.255.255", &netmask.addr);
|
||||
pico_ipv4_link_add(tun, ipaddr, netmask);
|
||||
#endif
|
||||
|
||||
// Default route
|
||||
pico_string_to_ipv4("192.168.166.1", &ipaddr.addr);
|
||||
pico_ipv4_route_add(zero, zero, ipaddr, 1, NULL);
|
||||
|
||||
pico_ppp_set_serial_read(ppp, modem_read);
|
||||
pico_ppp_set_serial_write(ppp, modem_write);
|
||||
pico_ppp_set_serial_set_speed(ppp, modem_set_speed);
|
||||
|
||||
pico_ppp_connect(ppp);
|
||||
|
||||
#ifdef DHCP
|
||||
if (pico_dhcp_initiate_negotiation(tap, &callback_dhcpclient, &dhcpclient_xid) < 0)
|
||||
{
|
||||
printf("%s: error initiating negotiation: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void stop_pico()
|
||||
{
|
||||
if (ppp)
|
||||
{
|
||||
pico_ppp_destroy(ppp);
|
||||
ppp = NULL;
|
||||
}
|
||||
if (tap)
|
||||
{
|
||||
pico_device_destroy(tap);
|
||||
tap = NULL;
|
||||
}
|
||||
if (tun)
|
||||
{
|
||||
pico_device_destroy(tun);
|
||||
tun = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
bool start_pico();
|
||||
void stop_pico();
|
||||
void write_pico(u8 b);
|
||||
int read_pico();
|
|
@ -22,13 +22,16 @@
|
|||
*/
|
||||
#include "types.h"
|
||||
|
||||
#if HOST_OS == OS_LINUX
|
||||
#if 1//HOST_OS == OS_LINUX
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include "oslib/oslib.h"
|
||||
#include "pppd.h"
|
||||
|
||||
static int pppd_pid;
|
||||
|
@ -38,6 +41,11 @@ static int outpipe = -1;
|
|||
static u8 in_buffer[128];
|
||||
static int in_bufsize;
|
||||
static int in_bufindex;
|
||||
static bool v42_negotiate = false;
|
||||
static u32 v42_odp_idx;
|
||||
static u32 v42_odp_count;
|
||||
const u8 v42_odp[] { 0x45, 0xfc, 0x17, 0xf9, 0x5f, 0xc4, 0x7f, 0x91, 0xff };
|
||||
double last_adp_sent;
|
||||
|
||||
void start_pppd()
|
||||
{
|
||||
|
@ -75,6 +83,9 @@ void start_pppd()
|
|||
inpipe = inpipefd[0];
|
||||
outpipe = outpipefd[1];
|
||||
fcntl(inpipe, F_SETFL, fcntl(inpipe, F_GETFL) | O_NONBLOCK);
|
||||
in_bufindex = 0;
|
||||
in_bufsize = 1;
|
||||
in_buffer[0] = 0;
|
||||
}
|
||||
|
||||
void stop_pppd()
|
||||
|
@ -97,8 +108,89 @@ void stop_pppd()
|
|||
}
|
||||
}
|
||||
|
||||
static u8 reverse_bits(u8 x)
|
||||
{
|
||||
x = ((x * 0x0802 & 0x22110) | (x * 0x8020 & 0x88440)) * 0x10101 >> 16;
|
||||
|
||||
return x & 0xFF;
|
||||
}
|
||||
|
||||
static void send_v42_adp()
|
||||
{
|
||||
in_bufsize = 0;
|
||||
in_bufindex = 0;
|
||||
|
||||
// V.42 disabled E, 8-16 ones, NULL, 8-16 ones // FIXME leading one is a test
|
||||
const std::string adp_nov42("1" "0101000101" "11111111" "0000000001" "11111111");
|
||||
const std::string adp_v42("1" "0101000101" "11111111" "0110000101" "11111111");
|
||||
const std::string& adp = adp_nov42;
|
||||
const std::string ones("1111111111111111");
|
||||
|
||||
int adp_idx = 0;
|
||||
for (int i = 0; i < 10; )
|
||||
{
|
||||
int end = min(adp_idx + 8, (int)adp.length());
|
||||
std::string binary = adp.substr(adp_idx, end - adp_idx);
|
||||
adp_idx += 8;
|
||||
|
||||
if (adp_idx > end)
|
||||
{
|
||||
adp_idx -= adp.length();
|
||||
if (i == 9)
|
||||
binary += ones.substr(0, adp_idx);
|
||||
else
|
||||
binary += adp.substr(0, adp_idx);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (adp_idx >= adp.length())
|
||||
{
|
||||
adp_idx = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
std::bitset<8> bs(binary);
|
||||
in_buffer[in_bufsize++] = reverse_bits(bs.to_ulong());
|
||||
if (in_bufsize == sizeof(in_buffer))
|
||||
{
|
||||
printf("PPPD in buffer overflow\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v42_negotiate = false;
|
||||
}
|
||||
|
||||
void write_pppd(u8 b)
|
||||
{
|
||||
if (v42_negotiate)
|
||||
{
|
||||
if (b == v42_odp[v42_odp_idx])
|
||||
{
|
||||
v42_odp_idx++;
|
||||
if (v42_odp_idx >= sizeof(v42_odp))
|
||||
{
|
||||
v42_odp_count++;
|
||||
if (v42_odp_count >= 2)
|
||||
{
|
||||
if (last_adp_sent == 0 || os_GetSeconds() - last_adp_sent > 0.75) // T400
|
||||
{
|
||||
printf("PPPD V42 2 ODP received. Sending ADP\n");
|
||||
last_adp_sent = os_GetSeconds();
|
||||
send_v42_adp();
|
||||
}
|
||||
v42_odp_count = 0;
|
||||
}
|
||||
v42_odp_idx = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v42_odp_idx = 0;
|
||||
printf("PPPD ignored byte %02x\n", b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
int rc = write(outpipe, &b, 1);
|
||||
if (rc < 0)
|
||||
perror("write outpipe");
|
||||
|
@ -110,6 +202,11 @@ int read_pppd()
|
|||
{
|
||||
if (in_bufindex == in_bufsize)
|
||||
{
|
||||
in_bufindex = 0;
|
||||
in_bufsize = 0;
|
||||
if (v42_negotiate)
|
||||
return -1;
|
||||
|
||||
int rc = read(inpipe, in_buffer, sizeof(in_buffer));
|
||||
if (rc < 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue