1use anyhow::Result;
2use get_if_addrs::get_if_addrs;
3use std::net::IpAddr;
4
5pub fn get_first_non_loopback_interface() -> Result<IpAddr> {
6 for i in get_if_addrs()? {
7 if !i.is_loopback() {
8 match i.addr {
9 get_if_addrs::IfAddr::V4(ref addr) => return Ok(std::net::IpAddr::V4(addr.ip)),
10 _ => continue,
11 }
12 }
13 }
14 Err(anyhow::anyhow!("No IPV4 interface found"))
15}
16pub fn is_private_ip(ip: &IpAddr) -> bool {
18 match ip {
19 IpAddr::V4(ipv4) => {
20 if ipv4.octets()[0] == 10 {
23 return true;
24 }
25 if ipv4.octets()[0] == 172 && (ipv4.octets()[1] & 0xf0) == 16 {
27 return true;
28 }
29 if ipv4.octets()[0] == 192 && ipv4.octets()[1] == 168 {
31 return true;
32 }
33 if ipv4.octets()[0] == 127 {
35 return true;
36 }
37 if ipv4.octets()[0] == 169 && ipv4.octets()[1] == 254 {
39 return true;
40 }
41 false
42 }
43 IpAddr::V6(ipv6) => {
44 if (ipv6.octets()[0] & 0xfe) == 0xfc {
46 return true;
47 }
48 if ipv6.is_loopback() {
50 return true;
51 }
52 if (ipv6.octets()[0] == 0xfe) && ((ipv6.octets()[1] & 0xc0) == 0x80) {
54 return true;
55 }
56 false
57 }
58 }
59}
60
61pub fn extract_rtp_addresses_from_sdp(sdp: &str) -> Result<Vec<IpAddr>> {
63 let mut addresses = Vec::new();
64
65 for line in sdp.lines() {
66 if line.starts_with("c=") {
67 let parts: Vec<&str> = line.splitn(4, ' ').collect();
69 if parts.len() >= 3 {
70 if let Ok(addr) = parts[2].parse::<IpAddr>() {
71 addresses.push(addr);
72 }
73 }
74 }
75 }
76
77 Ok(addresses)
78}
79
80pub fn sdp_contains_private_ip(sdp: &str) -> Result<bool> {
82 let addresses = extract_rtp_addresses_from_sdp(sdp)?;
83 Ok(addresses.iter().any(is_private_ip))
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use std::net::{Ipv4Addr, Ipv6Addr};
90
91 #[test]
92 fn test_is_private_ip() {
93 assert!(is_private_ip(&IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))));
95 assert!(is_private_ip(&IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))));
96 assert!(is_private_ip(&IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))));
97 assert!(is_private_ip(&IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
98 assert!(is_private_ip(&IpAddr::V4(Ipv4Addr::new(169, 254, 1, 1))));
99
100 assert!(!is_private_ip(&IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
102 assert!(!is_private_ip(&IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))));
103
104 assert!(is_private_ip(&IpAddr::V6(Ipv6Addr::new(
106 0xfc00, 0, 0, 0, 0, 0, 0, 1
107 ))));
108 assert!(is_private_ip(&IpAddr::V6(Ipv6Addr::LOCALHOST)));
109 assert!(is_private_ip(&IpAddr::V6(Ipv6Addr::new(
110 0xfe80, 0, 0, 0, 0, 0, 0, 1
111 ))));
112 }
113
114 #[test]
115 fn test_extract_rtp_addresses_from_sdp() {
116 let sdp = "v=0\r\n\
117 o=- 1234567890 1234567890 IN IP4 192.168.1.100\r\n\
118 s=Call\r\n\
119 c=IN IP4 192.168.1.100\r\n\
120 t=0 0\r\n\
121 m=audio 49170 RTP/AVP 0 8 97\r\n";
122
123 let addresses = extract_rtp_addresses_from_sdp(sdp).unwrap();
124 assert_eq!(addresses.len(), 1);
125 assert_eq!(addresses[0], IpAddr::V4(Ipv4Addr::new(192, 168, 1, 100)));
126 }
127
128 #[test]
129 fn test_sdp_contains_private_ip() {
130 let private_sdp = "v=0\r\n\
131 o=- 1234567890 1234567890 IN IP4 192.168.1.100\r\n\
132 s=Call\r\n\
133 c=IN IP4 192.168.1.100\r\n\
134 t=0 0\r\n\
135 m=audio 49170 RTP/AVP 0 8 97\r\n";
136
137 let public_sdp = "v=0\r\n\
138 o=- 1234567890 1234567890 IN IP4 8.8.8.8\r\n\
139 s=Call\r\n\
140 c=IN IP4 8.8.8.8\r\n\
141 t=0 0\r\n\
142 m=audio 49170 RTP/AVP 0 8 97\r\n";
143
144 assert!(sdp_contains_private_ip(private_sdp).unwrap());
145 assert!(!sdp_contains_private_ip(public_sdp).unwrap());
146 }
147}