<commit_before>package main

import (
	"crypto/aes"
	"crypto/rand"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/kanocz/lcvpn/netlink"
	"github.com/matishsiao/go_reuseport"
	"github.com/milosgajdos83/tenus"
	"github.com/songgao/water"
	"golang.org/x/net/ipv4"
)

const (
	// AppVersion contains current application version for -version command flag
	AppVersion = "0.2.0a"
)

const (
	// I use TUN interface, so only plain IP packet, no ethernet header + mtu is set to 1300

	// BUFFERSIZE is size of buffer to receive packets (little bit bigger than maximum)
	BUFFERSIZE = 1518
	// MTU used for tunneled packets
	MTU = 1300
)

func rcvrThread(proto string, port int, iface *water.Interface) {
	conn, err := reuseport.NewReusableUDPPortConn(proto, fmt.Sprintf(":%v", port))
	if nil != err {
		log.Fatalln("Unable to get UDP socket:", err)
	}

	encrypted := make([]byte, BUFFERSIZE)
	decrypted := make([]byte, BUFFERSIZE)

	for {
		n, _, err := conn.ReadFrom(encrypted)

		if err != nil {
			fmt.Println("Error: ", err)
			continue
		}

		// ReadFromUDP can return 0 bytes on timeout
		if 0 == n {
			continue
		}

		conf := config.Load().(VPNState)

		if !conf.Main.main.CheckSize(n) {
			fmt.Println("invalid packet size ", n)
			continue
		}

		ne := conf.Main.main.Decrypt(encrypted[:n], decrypted)
		size := int(decrypted[0]) + (256 * int(decrypted[1]))
		if 0 == ne || (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((decrypted)[2]>>4) {
			if nil != conf.Main.alt {
				ne = conf.Main.alt.Decrypt(encrypted[:n], decrypted)
				size := int(decrypted[0]) + (256 * int(decrypted[1]))
				if 0 == ne || (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((decrypted)[2]>>4) {
					fmt.Println("Invalid size field or IPv4 id in decrypted message", size, (n - aes.BlockSize - 2))
					continue
				}
			}
		}

		iface.Write(decrypted[2 : 2+size])
	}
}

func sndrThread(conn *net.UDPConn, iface *water.Interface) {
	// first time fill with random numbers
	ivbuf := make([]byte, config.Load().(VPNState).Main.main.IVLen())
	if _, err := io.ReadFull(rand.Reader, ivbuf); err != nil {
		log.Fatalln("Unable to get rand data:", err)
	}

	var packet IPPacket = make([]byte, BUFFERSIZE)
	var encrypted = make([]byte, BUFFERSIZE)

	for {
		plen, err := iface.Read(packet[2 : MTU+2])
		if err != nil {
			break
		}

		if 4 != packet.IPver() {
			header, _ := ipv4.ParseHeader(packet[2:])
			log.Printf("Non IPv4 packet [%+v]\n", header)
			continue
		}

		// each time get pointer to (probably) new config
		c := config.Load().(VPNState)

		dst := packet.Dst()

		wanted := false

		addr, ok := c.remotes[dst]

		if ok {
			wanted = true
		}

		if dst == c.Main.bcastIP || packet.IsMulticast() {
			wanted = true
		}

		// very ugly and useful only for a limited numbers of routes!
		if !wanted {
			ip := packet.DstV4()
			for n, s := range c.routes {
				if n.Contains(ip) {
					addr = s
					ok = true
					wanted = true
					break
				}
			}
		}

		if wanted {
			// store orig packet len
			packet[0] = byte(plen % 256)
			packet[1] = byte(plen / 256)

			// encrypt
			clen := c.Main.main.AdjustInputSize(plen + 2)

			if clen > len(packet) {
				log.Println("clen > len(package)", clen, len(packet))
				continue
			}

			tsize := c.Main.main.Encrypt(packet[:clen], encrypted, ivbuf)

			if ok {
				n, err := conn.WriteToUDP(encrypted[:tsize], addr)
				if nil != err {
					log.Println("Error sending package:", err)
				}
				if n != tsize {
					log.Println("Only ", n, " bytes of ", tsize, " sent")
				}
			} else {
				// multicast or broadcast
				for _, addr := range c.remotes {
					n, err := conn.WriteToUDP(encrypted[:tsize], addr)
					if nil != err {
						log.Println("Error sending package:", err)
					}
					if n != tsize {
						log.Println("Only ", n, " bytes of ", tsize, " sent")
					}
				}
			}
		} else {<commit_msg>Few style fixes<commit_after>package main

import (
	"crypto/aes"
	"crypto/rand"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/kanocz/lcvpn/netlink"
	"github.com/matishsiao/go_reuseport"
	"github.com/milosgajdos83/tenus"
	"github.com/songgao/water"
	"golang.org/x/net/ipv4"
)

const (
	// AppVersion contains current application version for -version command flag
	AppVersion = "0.2.0a"
)

const (
	// I use TUN interface, so only plain IP packet, no ethernet header + mtu is set to 1300

	// BUFFERSIZE is size of buffer to receive packets (little bit bigger than maximum)
	BUFFERSIZE = 1518
	// MTU used for tunneled packets
	MTU = 1300
)

func rcvrThread(proto string, port int, iface *water.Interface) {
	conn, err := reuseport.NewReusableUDPPortConn(proto, fmt.Sprintf(":%v", port))
	if nil != err {
		log.Fatalln("Unable to get UDP socket:", err)
	}

	encrypted := make([]byte, BUFFERSIZE)
	decrypted := make([]byte, BUFFERSIZE)

	for {
		n, _, err := conn.ReadFrom(encrypted)

		if err != nil {
			fmt.Println("Error: ", err)
			continue
		}

		// ReadFromUDP can return 0 bytes on timeout
		if 0 == n {
			continue
		}

		conf := config.Load().(VPNState)

		if !conf.Main.main.CheckSize(n) {
			fmt.Println("invalid packet size ", n)
			continue
		}

		ne := conf.Main.main.Decrypt(encrypted[:n], decrypted)
		// make int from 2x byte
		size := int(decrypted[0]) | (int(decrypted[1]) << 8)
		// check if decrypted size if ok and if this is a ipv4 packet
		// don't forward something is corrupted on other size OR encrypted with a wrong key
		if 0 == ne || (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((decrypted)[2]>>4) {
			if nil != conf.Main.alt {
				ne = conf.Main.alt.Decrypt(encrypted[:n], decrypted)
				size := int(decrypted[0]) | (int(decrypted[1]) << 8)
				if 0 == ne || (n-aes.BlockSize-2)-size > 16 || (n-aes.BlockSize-2)-size < 0 || 4 != ((decrypted)[2]>>4) {
					fmt.Println("Invalid size field or IPv4 id in decrypted message", size, (n - aes.BlockSize - 2))
					continue
				}
			}
		}

		iface.Write(decrypted[2 : 2+size])
	}
}

func sndrThread(conn *net.UDPConn, iface *water.Interface) {
	// first time fill with random numbers
	ivbuf := make([]byte, config.Load().(VPNState).Main.main.IVLen())
	if _, err := io.ReadFull(rand.Reader, ivbuf); err != nil {
		log.Fatalln("Unable to get rand data:", err)
	}

	var packet IPPacket = make([]byte, BUFFERSIZE)
	var encrypted = make([]byte, BUFFERSIZE)

	for {
		plen, err := iface.Read(packet[2 : MTU+2])
		if err != nil {
			break
		}

		if 4 != packet.IPver() {
			header, _ := ipv4.ParseHeader(packet[2:])
			log.Printf("Non IPv4 packet [%+v]\n", header)
			continue
		}

		// each time get pointer to (probably) new config
		c := config.Load().(VPNState)

		dst := packet.Dst()

		wanted := false

		addr, ok := c.remotes[dst]

		if ok {
			wanted = true
		}

		if dst == c.Main.bcastIP || packet.IsMulticast() {
			wanted = true
		}

		// very ugly and useful only for a limited numbers of routes!
		if !wanted {
			ip := packet.DstV4()
			for n, s := range c.routes {
				if n.Contains(ip) {
					addr = s
					ok = true
					wanted = true
					break
				}
			}
		}

		if wanted {
			// store orig packet len
			packet[0] = byte(plen & 0xff)
			packet[1] = byte((plen & 0xff00) >> 8)

			// new len contatins also 2byte original size
			clen := c.Main.main.AdjustInputSize(plen + 2)

			if clen > len(packet) {
				log.Println("clen > len(package)", clen, len(packet))
				continue
			}

			tsize := c.Main.main.Encrypt(packet[:clen], encrypted, ivbuf)

			if ok {
				n, err := conn.WriteToUDP(encrypted[:tsize], addr)
				if nil != err {
					log.Println("Error sending package:", err)
				}
				if n != tsize {
					log.Println("Only ", n, " bytes of ", tsize, " sent")
				}
			} else {
				// multicast or broadcast
				for _, addr := range c.remotes {
					n, err := conn.WriteToUDP(encrypted[:tsize], addr)
					if nil != err {
						log.Println("Error sending package:", err)
					}
					if n != tsize {
						log.Println("Only ", n, " bytes of ", tsize, " sent")
					}
				}
			}
		} else {
{'fraction_non_alphanumeric': 0.15779019242706394, 'fraction_numerical': 0.016635630043451272, 'mean_word_length': 2.86378896882494, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1097151', 'n_tokens_mistral': 3541, 'n_tokens_neox': 2973, 'n_words': 777}